A:【读题+细节】
【排序+贪心】
题意:
有n张牌,分给n/2个人,每人两张,要求每个人牌上的数值之和相等,输入保证有解。
题解:
先将所有牌面排序,那么依次给每个人分配【最小,最大】【次小,次大】。。。。。。即可【学习按关键字排序】
#include <iostream> #include <algorithm> #include <cmath> #include <cstring> #include <map> #include <vector> #include <queue> #include <list> #include <cstdio> #define IO ios_base::sync_with_stdio(0),cin.tie(0) #define N 105 #define INF 0x3f3f3f3f typedef long long ll; using namespace std; int n; struct Node{ int id,val; }node[N]; bool cmp(Node x, Node y){ return x.val < y.val; } int main() { while(cin >> n){ for(int i = 1;i <= n;++ i){ cin >> node[i].val; node[i].id = i; } sort(node+1, node+n+1, cmp); for(int i = 1;i <= n/2;++ i) cout << node[i].id << " " << node[n-i+1].id << endl; } return 0; }
B:【读题+细节】
题意:
给你t,s,x。且有一个序列是这样的t, t + s, t + s + 1, t + 2s, t + 2s + 1, 问你x是否存在这个序列当中
题解:
直接判断即可,注意1、x < t 2、 t+s*k+1 时必须有一个s
#include <iostream> #include <algorithm> #include <cmath> #include <cstring> #include <map> #include <vector> #include <queue> #include <list> #include <cstdio> #define IO ios_base::sync_with_stdio(0),cin.tie(0) #define N 105 #define INF 0x3f3f3f3f typedef long long ll; using namespace std; int t,x,s; int main() { while(cin >> t >> s >> x){ if(x < t){ cout << "NO" << endl; continue; } if((x-t)%s == 0 || ((x-t-1)%s == 0 && (x-t-1)/s != 0)) cout << "YES" << endl; else cout << "NO" << endl; } return 0; }
C:【求余+技巧】
题意:
给定两个数n,m。求有多少个数 (x+y)%5 == 0。1 <= x <= n, 1 <= y <= m;
题解:
朴素解法:
一个嵌套双重for循环去枚举,这样的话会超时。
优化:
题意要求能整除5的数字,那么考虑一下,其实只有 0+0,1+4,2+3,3+2,4+1 这四种情况。
其他的数字均可以转化成求这四种情况的问题,那么进行求余操作可以很优美的实现这个目的。
ps:这是个开放题,各种解法都是可以的。
#include <iostream> #include <algorithm> #include <cmath> #include <cstring> #include <map> #include <vector> #include <queue> #include <list> #include <cstdio> #define IO ios_base::sync_with_stdio(0),cin.tie(0) #define N 105 #define INF 0x3f3f3f3f typedef long long ll; using namespace std; int n,m; ll a[10],b[10]; int main() { while(cin >> n >> m){ memset(a, 0, sizeof(a)); memset(b, 0, sizeof(b)); for(int i = 1;i <= n;++ i) a[i%5]++; for(int i = 1;i <= m;++ i) b[i%5]++; ll ans = a[0]*b[0] + a[1]*b[4] + a[2]*b[3] + a[3]*b[2] + a[4]*b[1]; cout << ans << endl; } }
D:【读题】
题意:
balabala一大堆,其实就是让你判断是否有一个人成绩 after > before && before >= 2400
题解:
直接模拟这个过程就好
#include <iostream> #include <algorithm> #include <cmath> #include <cstring> #include <map> #include <vector> #include <queue> #include <list> #include <cstdio> #define IO ios_base::sync_with_stdio(0),cin.tie(0) #define N 105 #define INF 0x3f3f3f3f typedef long long ll; using namespace std; int n,after,before; string s; int main() { while(cin >> n){ int ok = 0; for(int i = 1;i <= n;++ i){ cin >> s >> before >> after; if(before >= 2400 && after > before) ok = 1; } cout << (ok == 1 ? "YES" : "NO") << endl; } return 0; }
E:【读题+模拟】
题意:
给你n个人要推墙,告诉你每个人的高度和墙的高度,如果人的高度 > 墙,需要消耗2能量,否则消耗1能量。求消耗总能量。
题解:
读懂题之后直接模拟
#include <iostream> #include <algorithm> #include <cmath> #include <cstring> #include <map> #include <vector> #include <queue> #include <list> #include <cstdio> #define IO ios_base::sync_with_stdio(0),cin.tie(0) #define N 105 #define INF 0x3f3f3f3f typedef long long ll; using namespace std; int x,n,h; int main() { while(cin >> n >> h){ int ans = 0; for(int i = 1;i <= n;++ i){ cin >> x; if(x > h) ans += 2; else ans += 1; } cout << ans << endl; } return 0; }
F:【直接构造 or 思维】
题意:
给定一个字符串是这个样子的 123456789101112131415....... 让你求第n个字符是多少。
题解:
一、
按照题意直接定义一个字符串,让它不断 +字符1,+字符2,+字符3......因为n最大1000,然后直接输出即可。n最大1000,所以不会超空间。
二、
首先通过n我们可以判断这一位是在 1位数,2位数,还是3位数。
其次,我们可以计算出该位数的数字是多少,通过减去低位的总数来计算。
最后,分类讨论一下该位数是这个数字的十位、百位、还是千位。
最后输出即可。
#include <iostream> #include <algorithm> #include <cmath> #include <cstring> #include <map> #include <vector> #include <queue> #include <list> #include <cstdio> #define IO ios_base::sync_with_stdio(0),cin.tie(0) #define N 105 #define INF 0x3f3f3f3f typedef long long ll; using namespace std; int n; int ans[3005]; void fuc(){ int len = 1; for(int i = 1;i <= 1000;++ i){ if(i < 10) ans[len++] = i; if(i >= 10 && i < 100){ ans[len++] = i/10; ans[len++] = i%10; } if(i >= 100){ ans[len++] = i/100; ans[len++] = (i/10)%10; ans[len++] = i%10; } } } int main() { fuc(); while(cin >> n){ cout << ans[n] << endl; } return 0; } /* 第二种解法: int n; int main() { while(cin >> n){ if(n < 10) cout << n << endl; if(n >= 10 && n <= 189){ int res = n-9; int num = (res%2 == 0 ? res/2 : res/2+1) + 9; cout << (res%2 == 0 ? num%10 : num/10) << endl; } if(n > 189 && n <= 1090){ int res = n-189; int num = (res%3 == 0 ? res/3 : res/3+1) + 99; if(res%3 == 0) cout << num%10 << endl; else if(res%3 == 1) cout << num/100 << endl; else if(res%3 == 2) cout << (num/10)%10 << endl; } } return 0; } */
G:【模拟】
题意:
给你三个数字n,a,b分别表示一个圆圈的点数,起点位置,需要走的步数。b > 0:顺时针,b < 0:逆时针。最后求这个人在哪个点。
题解:
根据起点+方向+步数直接模拟。注意考虑负数取模的情况。
#include <iostream> #include <algorithm> #include <cmath> #include <cstring> #include <map> #include <vector> #include <queue> #include <list> #include <cstdio> #define IO ios_base::sync_with_stdio(0),cin.tie(0) #define N 105 #define INF 0x3f3f3f3f typedef long long ll; using namespace std; int n,a,b; int main() { while(cin >> n >> a >> b){ if(b < 0) b = -(-b)%n; a += n; int ans = ((a+b)%n == 0 ? n : (a+b)%n); cout << ans << endl; } return 0; }
H:【简单判断+技巧】
题意:
给定n和x,表示有一个n*n的矩阵,每个点的元素值是i*j。求这个矩阵中x出现的次数;
题解:
朴素解法:写个双重for循环直接判断即可,但是题目n最大可能是1e5,两个嵌套循环会超时。
优化:考虑到每一行每个元素都可以用行号确定,因此枚举每一行,判断x/i的商是否在1-n之间即可
#include <iostream> #include <algorithm> #include <cmath> #include <cstring> #include <map> #include <vector> #include <queue> #include <list> #include <cstdio> #define IO ios_base::sync_with_stdio(0),cin.tie(0) #define N 105 #define INF 0x3f3f3f3f typedef long long ll; using namespace std; int n,x; int main() { while(cin >> n >> x){ int ans = 0; for(int i = 1;i <= n;++ i){ if(x%i == 0 && x/i >= 1 && x/i <= n) ans++; } cout << ans << endl; } return 0; }
I:【读题+排序】
题意:
给定n个人以及每个人的票数a[i],现在想让第一个人票数最高。
每个人可以给第一个人投票,投票后这个人的票数减少。
问这个人最少需要增加多少。
题解:
一、
每次从 2-n 这些人中选择最高的给第一个人投票,直到这些人的最高票数比第一个人低。
二、
可以采用c++STL里面的一个工具【优先队列】,实现每次得到最大或者最小数。有兴趣的同学可以百度.
#include <iostream> #include <algorithm> #include <cmath> #include <cstring> #include <map> #include <vector> #include <queue> #include <list> #include <cstdio> #define IO ios_base::sync_with_stdio(0),cin.tie(0) #define N 105 #define INF 0x3f3f3f3f typedef long long ll; using namespace std; int n,vote,a[N]; int main() { while(cin >> n){ cin >> vote; for(int i = 2;i <= n;++ i) cin >> a[i]; int ans = 0; while(true){ sort(a+2, a+1+n); if(vote > a[n]) break; ans++; vote++; a[n]--; } cout << ans << endl; } return 0; }
J:【读题+排序】
题意:
给你n个点在x轴的位置,求每个点与其它的最小距离和最大距离。
题解:
考虑到所有点都只在x轴上,那么可以将所有点进行排序。
考虑第i个点的位置,它与其它点的最小距离是去与它相邻的两个点的最小值。
即 : min(a[i+1]-a[i], a[i]-a[i-1])
最大值: max(a[i]-a[1], a[n]-a[i]);
特殊考虑一下第一个点和最后一个点即可
#include <iostream> #include <algorithm> #include <cmath> #include <cstring> #include <map> #include <vector> #include <queue> #include <list> #include <cstdio> #define IO ios_base::sync_with_stdio(0),cin.tie(0) #define N 100000+5 #define INF 0x3f3f3f3f typedef long long ll; using namespace std; int n,a[N]; int main() { while(cin >> n){ for(int i = 1;i <= n;++ i) cin >> a[i]; sort(a+1, a+n+1); cout << a[2]-a[1] << " " << a[n]-a[1] << endl; for(int i = 2;i < n;++ i){ cout << min(a[i+1]-a[i], a[i]-a[i-1]) << " "; cout << max(a[n]-a[i], a[i]-a[1]) << endl; } cout << a[n]-a[n-1] << " " << a[n]-a[1] << endl; } return 0; }