#include<iostream>#include<cstring>#include<vector>#include<list>#include<queue>#include<deque>#include<map>#include<stack>#include<set>#include<string>#include<algorithm>#include<unordered_map>usingnamespace std;#define_for(i,a,b)for(int i=(a);i<(b);i++)#define_rep(i,a,b)for(int i=(a);i<=(b);i++)typedefunsignedlonglong ULL;typedeflonglong ll;typedef pair<int,int> PII;intreadint(){int x;scanf("%d",&x);return x;}constint INF =0x3f3f3f3f;constint N =2e5+5;intmain(){int T; cin>>T;while(T--){char s[10];scanf("%s", s +1);bool ok =true;_rep(i,1,3){if(isupper(s[i])) s[i]=tolower(s[i]);}if(s[1]!='y'|| s[2]!='e'|| s[3]!='s') ok =false;if(ok)puts(" YES");elseputs(" NO");}return0;}
B ICPC Balloons
思路
统计每个数字出现的次数
如果某个数字出现的次数不为 0 就再加 1
代码
#include<iostream>#include<cstring>#include<vector>#include<list>#include<queue>#include<deque>#include<map>#include<stack>#include<set>#include<string>#include<algorithm>#include<unordered_map>usingnamespace std;#define_for(i,a,b)for(int i=(a);i<(b);i++)#define_rep(i,a,b)for(int i=(a);i<=(b);i++)typedefunsignedlonglong ULL;typedeflonglong ll;typedef pair<int,int> PII;intreadint(){int x;scanf("%d",&x);return x;}constint INF =0x3f3f3f3f;constint N =2e5+5;char s[55];int n, cnt[128];intmain(){int T; cin>>T;while(T--){memset(cnt,0,sizeof(cnt));
n =readint();scanf("%s", s +1);_rep(i ,1, n) cnt[s[i]]++;int res =0;_rep(i,'A','Z'){if(cnt[i]) cnt[i]++;
res += cnt[i];}printf(" %d\n", res);}return0;}
C Cypher
思路
给出了每位操作完的数字
则反向思维, 对于 D 则 + 1, U 则 - 1
加法减法都是在 mod 10 下的
减法可能出现负数, 所以先 + 10 再 mod 10
代码
#include<iostream>#include<cstring>#include<vector>#include<list>#include<queue>#include<deque>#include<map>#include<stack>#include<set>#include<string>#include<algorithm>#include<unordered_map>usingnamespace std;#define_for(i,a,b)for(int i=(a);i<(b);i++)#define_rep(i,a,b)for(int i=(a);i<=(b);i++)typedefunsignedlonglong ULL;typedeflonglong ll;typedef pair<int,int> PII;intreadint(){int x;scanf("%d",&x);return x;}constint INF =0x3f3f3f3f;constint N =2e5+5;int n, a[N];char op[N];intmain(){int T; cin>>T;while(T--){
n =readint();_rep(i,1, n) a[i]=readint();_rep(i,1, n){int x =readint();scanf("%s", op +1);_rep(j,1, x){if(op[j]=='D'){
a[i]=(a[i]+1)%10;}else{
a[i]=(a[i]-1+10)%10;}}}_rep(i,1, n)printf("%d ", a[i]);puts("");}return0;}
D Double Strings
思路
用哈希表记录每个字符串是否出现过
暴力枚举字符串的两个子串
第一个子串是从头开始的
第二个子串是剩余的
如果两个子串都存在, 则该字符串满足条件
代码
#include<iostream>#include<cstring>#include<vector>#include<list>#include<queue>#include<deque>#include<map>#include<stack>#include<set>#include<string>#include<algorithm>#include<unordered_map>usingnamespace std;#define_for(i,a,b)for(int i=(a);i<(b);i++)#define_rep(i,a,b)for(int i=(a);i<=(b);i++)typedefunsignedlonglong ULL;typedeflonglong ll;typedef pair<int,int> PII;intreadint(){int x;scanf("%d",&x);return x;}constint INF =0x3f3f3f3f;constint N =1e5+5;int n;
string ss[N];
unordered_map<string,bool> isExist;intmain(){int T; cin>>T;while(T--){
isExist.clear();
n =readint();_rep(i,1, n){
cin >> ss[i];
isExist[ss[i]]=true;}_rep(i,1, n){int len = ss[i].length();bool ok =false;// 从 0 开始枚举子串长度, 看两部分是否都存在for(int j =1; j < len; j++){if(isExist[ss[i].substr(0, j)]&&
isExist[ss[i].substr(j)]){
ok =true;}}if(ok)printf("1");elseprintf("0");}puts("");}return0;}
E Mirror Grid
思路
坐标(x, y)旋转90°后的坐标是(y, n - x + 1)
每个坐标顺时针旋转多次后机会回到原坐标, 所以经过的这些坐标构成一个集合
要想方阵顺时针旋转都不变, 则只需让一个集合中的坐标数值一样即可
代码
#include<iostream>#include<cstring>#include<vector>#include<list>#include<queue>#include<deque>#include<map>#include<stack>#include<set>#include<string>#include<algorithm>#include<unordered_map>usingnamespace std;#define_for(i,a,b)for(int i=(a);i<(b);i++)#define_rep(i,a,b)for(int i=(a);i<=(b);i++)typedefunsignedlonglong ULL;typedeflonglong ll;typedef pair<int,int> PII;intreadint(){int x;scanf("%d",&x);return x;}constint INF =0x3f3f3f3f;constint N =2e5+5;int n;char s[101][101];bool vis[101][101];int ans =0;voidcount(int x,int y){//printf("%d %d\n", x, y);int zero =0, one =0;
vis[x][y]=true;if(s[x][y]=='1') one++;if(s[x][y]=='0') zero++;_rep(i,1,3){int xx = y, yy = n - x +1;if(xx == x && yy == y)break;//printf("%d %d\n", xx, yy);
x = xx, y = yy;
vis[xx][yy]=true;if(s[xx][yy]=='1') one++;if(s[xx][yy]=='0') zero++;}//printf("ans : %d\n", ans);
ans +=min(zero, one);}// 对于可以通过旋转到达的位置记为一类// 一类的位置上的数字要一样, 统计出一类数字出现的 0 和 1, 就能知道使一类相同的最小修改次数// 对于一个位置 (x, y)// 与(x, y) 一类的数字是通过 x' = y, y' = n - x + 1, 推出的// 对于 n 为奇数, 中心位置, 通过旋转仍是自己 // 对每一类的 0 和 1 进行统计, 哪个出现次数少, 就是最小修改次数// 对于一类的位置, 只需访问一次, 所以用 vis[x][y] 标记 (x, y) 是否倍访问intmain(){int T =readint();while(T--){
ans =0;memset(vis,false,sizeof(vis));
n =readint();_rep(i,1, n){scanf("%s", s[i]+1);}_rep(i,1, n){_rep(j,1, n){if(!vis[i][j])count(i, j);}}printf(" %d\n", ans);}return0;}
F. Yet Another Problem About Pairs Satisfying an Inequality
思路
对于满足条件的数字依次遍历
当遍历到 a[i] 时二分出最后一个小于 a[i] 的位置 j
则前 j 个位置中满足条件的数的位置 j 就能和 i 构成满足条件的(i, j)
代码
#include<iostream>usingnamespace std;#define_for(i,a,b)for(int i=(a);i<(b);i++)#define_rep(i,a,b)for(int i=(a);i<=(b);i++)typedefunsignedlonglong ULL;typedeflonglong ll;typedef pair<int,int> PII;intreadint(){int x;scanf("%d",&x);return x;}constint INF =0x3f3f3f3f;constint N =2e5+5;// b[i] 表示第 i 个数是否满足条件int n, a[N], b[N], s[N];// 对于数字 a[i] 如果 a[i] < i 称为满足条件的数// 因为我没用 vector, 所以用一个前缀和 s[i] 统计前 i 位置中满足条件的数的个数// 为什么可以二分// 因为 index 是上升的, 如果 j >= a[i], 则 j + 1 必定 > a[i]// 所以只有 j 前面的位置才 < a[i]intmain(){int T; cin>>T;while(T--){memset(b,0,sizeof(b));memset(s,0,sizeof(s));
n =readint();_rep(i ,1, n){
a[i]=readint();if(a[i]< i) b[i]=1;
s[i]= s[i -1]+ b[i];}
ll ans =0;// 对于每个位置满足条件的数的位置 i// 找到 < a[i] 的最后一个位置 j , 则 s[j] 就是 与 a[i]的 i 构成 满足条件的 (i, j)的个数_rep(i,1, n)if(b[i]){int L =0, R = n;// 找到小于 a[i] 的最右端的数while(L +1< R){int M =(L + R)/2;if(M < a[i]) L = M;else R = M;}// L 就是最一个 < a[i] 的数
ans += s[L];}printf("%lld\n", ans);}return0;}
G. Good Key, Bad Key
思路
贪心
先 goodkey 一定比先 badkey 要好
所以, 枚举使用 goodkey 和 badkey 的分界点
分别计算收获的金币数
更新最大值
a[i] 最大为 1e9, 所以最多整除 30 (log1e9) 就变成0了
代码
#include<iostream>#include<cstring>usingnamespace std;#define_for(i,a,b)for(int i=(a);i<(b);i++)#define_rep(i,a,b)for(int i=(a);i<=(b);i++)typedefunsignedlonglong ULL;typedef pair<int,int> PLL;typedeflonglong ll;constint N =1e5+5;constint INF =0x3f3f3f3f;intreadint(){int x;scanf("%d",&x);return x;}int n, k, a[N];
ll s[N];intmain(){int T =readint();while(T--){memset(s,0,sizeof(s));
n =readint(), k =readint();_rep(i,1, n){
a[i]=readint();
s[i]= s[i -1]+ a[i];}
ll ans =0;// 枚举前 i 个用 good key, 从 0 开始_rep(i,0, n){
ll x = s[i]-1LL* i * k;// i * k 会爆 int // 用右移就能算出, 后面 1/2 的次幂// j 最多枚举 30 次, 30次后右移结果为 0_rep(j, i +1,min(n, i +31)){
x += a[j]>>(j - i);}
ans =max(ans, x);}printf("%lld\n", ans);}return0;}