1.区间嵌套
https://www.acwing.com/problem/content/description/5462/
2.卡片
https://www.lanqiao.cn/problems/1443/learning/?page=1&first_category_id=1&second_category_id=3&name=%E5%8D%A1%E7%89%87
3.逆序对https://www.luogu.com.cn/problem/P1908
4.合唱队形
https://www.luogu.com.cn/problem/P1091
5.回文日期
https://www.lanqiao.cn/problems/498/learning/?page=1&first_category_id=1&second_category_id=3&name=%E5%9B%9E%E6%96%87%E6%97%A5%E6%9C%9F
6.既约分数
https://www.lanqiao.cn/problems/593/learning/?page=1&first_category_id=1&second_category_id=3&name=%E6%97%A2%E7%BA%A6%E5%88%86%E6%95%B0
7.数的分解
https://www.lanqiao.cn/problems/606/learning/?page=1&first_category_id=1&second_category_id=3&name=%E6%95%B0%E7%9A%84%E5%88%86%E8%A7%A3
8.九宫幻方
https://www.lanqiao.cn/problems/100/learning/?page=1&first_category_id=1&second_category_id=3&name=%E4%B9%9D%E5%AE%AB%E5%B9%BB%E6%96%B9
区间嵌套https://www.acwing.com/problem/content/description/5462/
给定 n� 个正整数区间,编号 1∼n1∼�。
其中,第 i� 个区间为 [li,ri][��,��]。
请你找到一对不同的整数 j,k�,�(1≤j,k≤n1≤�,�≤�),使得区间 j� 完全包含于区间 k�。
如果 lj≥lk��≥�� 且 rj≤rk��≤��,则区间 j� 完全包含于区间 k�。
输入格式
第一行包含整数 n�。
接下来 n� 行,其中第 i� 行包含两个整数 li,ri��,��。
输出格式
如果题目无解,则输出一行
-1 -1
。否则,在一行内输出一对不同的整数 j,k�,�,满足区间 j� 完全包含于区间 k�。
如果答案不唯一,则输出任意合理答案均可。
数据范围
前 66 个测试点满足 1≤n≤51≤�≤5。
所有测试点满足 1≤n≤3×1051≤�≤3×105,1≤li≤ri≤1091≤��≤��≤109。输入样例1:
5 1 10 2 9 3 9 2 3 2 9
输出样例1:
2 1
输入样例2:
3 1 5 2 6 6 20
输出样例2:
-1 -1
思路:按照左区间从大到小排序,然后比较相邻节点的右区间大小
#include <bits/stdc++.h>
using namespace std;
#define lowbit(x) (x& - (x))
#define int long long
#define INF 0x3f3f3f3fconst int N=3e5+5;struct node{int l;int r;int idx;
};node e[N];
bool cmp(const node&a ,const node &b){if (a.l==b.l) return a.r>b.r;else return a.l<b.l;
}
signed main(){int n;cin>>n;for (int i=1;i<=n;++i){cin>>e[i].l>>e[i].r;e[i].idx=i;}sort(e+1,e+1+n,cmp);for (int i=1;i<n;++i){if (e[i].r>=e[i+1].r){cout<<e[i+1].idx<<" "<<e[i].idx;return 0;}}cout<<-1<<" "<<-1;return 0;
}
卡片
https://www.lanqiao.cn/problems/1443/learning/?page=1&first_category_id=1&second_category_id=3&name=%E5%8D%A1%E7%89%87
小蓝有很多数字卡片,每张卡片上都是数字 00 到 99。
小蓝准备用这些卡片来拼一些数,他想从 11 开始拼出正整数,每拼一个,就保存起来,卡片就不能用来拼其它数了。
小蓝想知道自己能从 11 拼到多少。
例如,当小蓝有 3030 张卡片,其中 00 到 99 各 33 张,则小蓝可以拼出 11 到 1010,
但是拼 1111 时卡片 11 已经只有一张了,不够拼出 1111。
现在小蓝手里有 00 到 99 的卡片各 20212021 张,共 2021020210 张,请问小蓝可以从 11 拼到多少?
思路:暴力模拟
#include <iostream>
using namespace std;
int a[10];
void cc(int b){while (b>0){a[b%10]++;b/=10;}
}
bool check(){for (int i=0;i<10;++i){if (a[i]>2021)return true;}return false;
}
int main()
{for (int i=1;i<=4400;++i){cc(i);if (check()){cout<<i-1;return 0;}}return 0;
}
逆序对https://www.luogu.com.cn/problem/P1908
题目描述
猫猫 TOM 和小老鼠 JERRY 最近又较量上了,但是毕竟都是成年人,他们已经不喜欢再玩那种你追我赶的游戏,现在他们喜欢玩统计。
最近,TOM 老猫查阅到一个人类称之为“逆序对”的东西,这东西是这样定义的:对于给定的一段正整数序列,逆序对就是序列中 ��>��ai>aj 且 �<�i<j 的有序对。知道这概念后,他们就比赛谁先算出给定的一段正整数序列中逆序对的数目。注意序列中可能有重复数字。
Update:数据已加强。
输入格式
第一行,一个数 �n,表示序列中有 �n个数。
第二行 �n 个数,表示给定的序列。序列中每个数字不超过 109109。
输出格式
输出序列中逆序对的数目。
输入输出样例
输入 #1复制
6
5 4 2 6 3 1输出 #1复制
11
说明/提示
对于 25%25% 的数据,�≤2500n≤2500
对于 50%50% 的数据,�≤4×104n≤4×104。
对于所有数据,�≤5×105n≤5×105
思路:树状数组+离散化
#include <bits/stdc++.h>
using namespace std;
#define lowbit(x) (x& - (x))
#define int long long
#define INF 0x3f3f3f3fconst int N=5e5+5;
int n,Rank[N],tree[N];struct node{int val;int num;
}a[N];bool cmp(const node& a, const node& b){if (a.val==b.val) return a.num<b.num;return a.val<b.val;
}void update(int x,int c){while (x<=N){tree[x]+=c;x+=lowbit(x);}
}int query(int x){int res=0;while (x>0){res+=tree[x];x-=lowbit(x);}return res;
}signed main(){cin>>n;for (int i=1;i<=n;++i){cin>>a[i].val;a[i].num=i;}sort(a+1,a+1+n,cmp);for (int i=1;i<=n;++i){Rank[a[i].num]=i;}int sum=0;for (int i=n;i>0;--i){update(Rank[i],1);sum+=query(Rank[i]-1);}cout<<sum;
}
合唱队形https://www.luogu.com.cn/problem/P1091
题目描述
�n 位同学站成一排,音乐老师要请其中的 �−�n−k 位同学出列,使得剩下的 �k 位同学排成合唱队形。
合唱队形是指这样的一种队形:设 �k 位同学从左到右依次编号为 1,2,1,2, … ,�,k,他们的身高分别为 �1,�2,t1,t2, … ,��,tk,则他们的身高满足 �1<⋯<��>��+1>t1<⋯<ti>ti+1> … >��(1≤�≤�)>tk(1≤i≤k)。
你的任务是,已知所有 �n 位同学的身高,计算最少需要几位同学出列,可以使得剩下的同学排成合唱队形。
输入格式
共二行。
第一行是一个整数 �n(2≤�≤1002≤n≤100),表示同学的总数。
第二行有 �n 个整数,用空格分隔,第 �i 个整数 ��ti(130≤��≤230130≤ti≤230)是第 �i 位同学的身高(厘米)。
输出格式
一个整数,最少需要几位同学出列。
输入输出样例
输入 #1复制
8
186 186 150 200 160 130 197 220输出 #1复制
4
说明/提示
对于 50%50% 的数据,保证有 �≤20n≤20。
对于全部的数据,保证有 �≤100n≤100。
思路:动态规划,找最长单增子串,从左往右和从右往左都要遍历,然后重新遍历数组最高点,找到结果
#include <bits/stdc++.h>
using namespace std;
#define lowbit(x) (x& - (x))
#define int long long
#define INF 0x3f3f3f3fint dp1[105],dp2[105];
int n,a[105];signed main(){cin>>n;for (int i=1;i<=n;++i) cin>>a[i];for (int i=1;i<=n;++i){dp1[i]=1;dp2[i]=1;}for (int i=1;i<=n;++i){for (int j=1;j<i;++j){if (a[j]<a[i]) dp1[i]=max(dp1[i],dp1[j]+1);}}for (int i=n;i>=1;--i){for (int j=n;j>i;--j){if (a[j]<a[i]) dp2[i]=max(dp2[i],dp2[j]+1);}}int res=0;for (int i=1;i<=n;++i){res=max(res,(dp1[i]+dp2[i]-1));}cout<<n-res;
}
回文日期
https://www.lanqiao.cn/problems/498/learning/?page=1&first_category_id=1&second_category_id=3&name=%E5%9B%9E%E6%96%87%E6%97%A5%E6%9C%9F
2020 年春节期间,有一个特殊的日期引起了大家的注意:2020 年 2 月 2 日。因为如果将这个日期按 “yyyymmdd” 的格式写成一个 8 位数是 20200202,恰好是一个回文数。我们称这样的日期是回文日期。
有人表示 20200202 是 “千年一遇” 的特殊日子。对此小明很不认同,因为不到 2 年之后就是下一个回文日期:20211202 即 2021 年 12 月 2 日。
也有人表示 20200202 并不仅仅是一个回文日期,还是一个 ABABBABA 型的回文日期。对此小明也不认同,因为大约 100 年后就能遇到下一个 ABABBABA 型的回文日期:21211212 即 2121 年 12 月 12 日。算不上 “千年一遇”,顶多算 “千年两遇”。
给定一个 8 位数的日期,请你计算该日期之后下一个回文日期和下一个 ABABBABA 型的回文日期各是哪一天。
输入描述
输入包含一个八位整数 �N,表示日期。
对于所有评测用例,10000101≤�≤8999123110000101≤N≤89991231,保证 �N 是一个合法日期的 8 位数表示。
输出描述
输出两行,每行 1 个八位数。第一行表示下一个回文日期,第二行表示下一个 ABABBABA 型的回文日期。
#include <bits/stdc++.h>
using namespace std;
#define lowbit(x) (x& - (x))
#define int long long
#define INF 0x3f3f3f3fint days[13]={-1,31,28,31,30,31,30,31,31,30,31,30,31};string check(int date){string s=to_string(date),t=to_string(date);reverse(t.begin(),t.end());s+=t;int y=stoi(s.substr(0,4)),m=stoi(s.substr(4,2)),d=stoi(s.substr(6,2));if (y%400==0 || (y%4==0 && y%100!=0)) days[2]=29;else days[2]=28;if (m<1 || m>12 || d>days[m] || d<1) return "-1";return s;
}string check2(int date){string s=to_string(date),t=to_string(date);reverse(t.begin(),t.end());s+=t;if (s[0]==s[2] && s[1]==s[3]) return s;return "-1";
}signed main(){int date;cin>>date;string ans=" ";for (int i=date/10000;;++i){if (check(i)=="-1" || check(i)==to_string(date)) continue;if (ans==" ") ans=check(i);if (check2(i)!="-1"){cout<<ans<<endl<<check2(i);return 0;}}
}
既约分数
https://www.lanqiao.cn/problems/593/learning/?page=1&first_category_id=1&second_category_id=3&name=%E6%97%A2%E7%BA%A6%E5%88%86%E6%95%B0
如果一个分数的分子和分母的最大公约数是 11,这个分数称为既约分数。
例如 34,18,7143,81,17, 都是既约分数。
请问,有多少个既约分数,分子和分母都是 11 到 20202020 之间的整数(包括 11 和 20202020)?
#include <bits/stdc++.h>
using namespace std;
#define lowbit(x) (x& - (x))
#define int long long
#define INF 0x3f3f3f3fint gcd(int a,int b){if (b==0) return a;return gcd(b,a%b);
}signed main(){int cnt=0;for (int i=1;i<=2020;++i){for (int j=1;j<=2020;++j){if (gcd(i,j)==1) cnt++;}}cout<<cnt;
}
数的分解
https://www.lanqiao.cn/problems/606/learning/?page=1&first_category_id=1&second_category_id=3&name=%E6%95%B0%E7%9A%84%E5%88%86%E8%A7%A3
把 20192019 分解成 33 个各不相同的正整数之和,并且要求每个正整数都不包含数字 22 和 44,一共有多少种不同的分解方法?
注意交换 33 个整数的顺序被视为同一种方法,例如 1000+1001+181000+1001+18 和 1001+1000+181001+1000+18 被视为同一种。
#include <iostream>
using namespace std;bool hefa(int a){while (a>0){int m=a%10;a/=10;if (m==2 || m==4) return false;}return true;
}int main()
{int cnt=0;for(int i=1;i<=2019;++i){for (int j=i+1;j<2019-i-j;++j){if (hefa(i) && hefa(j) && hefa(2019-i-j)){cnt++;}}}cout<<cnt;return 0;
}
九宫幻方
https://www.lanqiao.cn/problems/100/learning/?page=1&first_category_id=1&second_category_id=3&name=%E4%B9%9D%E5%AE%AB%E5%B9%BB%E6%96%B9
小明最近在教邻居家的小朋友小学奥数,而最近正好讲述到了三阶幻方这个部分,三阶幻方指的是将 1~9 不重复的填入一个 3*3 的矩阵当中,使得每一行、每一列和每一条对角线的和都是相同的。
三阶幻方又被称作九宫格,在小学奥数里有一句非常有名的口诀:"二四为肩,六八为足,左三右七,戴九履一,五居其中",通过这样的一句口诀就能够非常完美的构造出一个九宫格来。
4 9 2
3 5 7
8 1 6
有意思的是,所有的三阶幻方,都可以通过这样一个九宫格进行若干镜像和旋转操作之后得到。现在小明准备将一个三阶幻方(不一定是上图中的那个)中的一些数抹掉,交给邻居家的小朋友来进行还原,并且希望她能够判断出究竟是不是只有一个解。
而你呢,也被小明交付了同样的任务,但是不同的是,你需要写一个程序。
输入描述
输入仅包含单组测试数据。
每组测试数据为一个 3*3 的矩阵,其中为 0 的部分表示被小明抹去的部分。
给出的矩阵至少能还原出一组可行的三阶幻方。
输出描述
如果仅能还原出一组可行的三阶幻方,则将其输出,否则输出"Too Many"(不包含引号)。
思路:DFS找空格内的字符,然后判断是否可以
#include <bits/stdc++.h>
using namespace std;
#define lowbit(x) (x& - (x))
#define int long long
#define INF 0x3f3f3f3f
int n=0;
int a[10][10],ans[10][10],vis[10],cnt=0;
pair<int,int>p[10];
bool check(){int p=a[1][1]+a[3][3]+a[2][2];for (int i=1;i<=3;++i){int m=0,c=0;for (int j=1;j<=3;++j){m+=a[i][j];c+=a[j][i];}if (m!=p|| c!=p) return false;}if (p!=a[1][3]+a[2][2]+a[3][1]) return false;return true;
}void dfs(int now){if (now>n){if(check()){cnt++;for (int i=1;i<=3;++i){for (int j=1;j<=3;++j){ans[i][j]=a[i][j];}}}return ;}int x=p[now].first,y=p[now].second;for (int k=1;k<=9;++k){if (vis[k]) continue;a[x][y]=k;vis[k]=1;dfs(now+1);a[x][y]=0;vis[k]=0;}
}signed main(){for (int i=1;i<=3;++i){for (int j=1;j<=3;++j){cin>>a[i][j];if (!a[i][j]) p[++ n]=make_pair(i,j);vis[a[i][j]]=1;}}dfs(1);if (cnt!=1){cout<<"Too Many";return 0;}else if (cnt==1){for (int i=1;i<=3;++i){for (int j=1;j<=3;++j){cout<<ans[i][j]<<" ";}cout<<endl;}}
}