CodeForces Round #499 Div2
题意:
给你n个字符, 现在需要从中选取m个字符,每个字符的花费为在字母表的第几位,并且如果选了某个字符, 那么下一个选择的字符必须要在字母表的2位之后, 假如选了e 那么 不能选 a-f 可以选择 g-z, 现在求能满足条件的最小花费。
题解:
直接模拟。
代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define Fopen freopen("_in.txt","r",stdin); freopen("_out.txt","w",stdout); 4 #define LL long long 5 #define ULL unsigned LL 6 #define fi first 7 #define se second 8 #define pb push_back 9 #define lson l,m,rt<<1 10 #define rson m+1,r,rt<<1|1 11 #define max3(a,b,c) max(a,max(b,c)) 12 #define min3(a,b,c) min(a,min(b,c)) 13 typedef pair<int,int> pll; 14 const int inf = 0x3f3f3f3f; 15 const LL INF = 0x3f3f3f3f3f3f3f3f; 16 const LL mod = (int)1e9+7; 17 const int N = 1e5 + 10; 18 int cnt[N]; 19 char s[N]; 20 int main(){ 21 int n, m; 22 scanf("%d%d", &n, &m); 23 scanf("%s", s+1); 24 for(int i = 1; i <= n; i++){ 25 cnt[s[i]-'a']++; 26 } 27 int ans = 0; 28 for(int i = 0; i < 26 && m; i++){ 29 if(cnt[i]){ 30 m--; 31 ans += i+1; 32 i++; 33 } 34 } 35 if(m) puts("-1"); 36 else printf("%d\n", ans); 37 return 0; 38 }
题意:
有n个人要去火星, 现在有m份食物, 每个人在火星生存的时候一天消耗一份食物, 并且每天的消耗的食物必须是同一种类的, 不同的人可以选择不同种类的食物。 现在求这n个人最多能在火星上待几天。
题解:
暴力模拟。
代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define Fopen freopen("_in.txt","r",stdin); freopen("_out.txt","w",stdout); 4 #define LL long long 5 #define ULL unsigned LL 6 #define fi first 7 #define se second 8 #define pb push_back 9 #define lson l,m,rt<<1 10 #define rson m+1,r,rt<<1|1 11 #define max3(a,b,c) max(a,max(b,c)) 12 #define min3(a,b,c) min(a,min(b,c)) 13 typedef pair<int,int> pll; 14 const int inf = 0x3f3f3f3f; 15 const LL INF = 0x3f3f3f3f3f3f3f3f; 16 const LL mod = (int)1e9+7; 17 const int N = 1e5 + 10; 18 int cnt[N]; 19 int main(){ 20 int n, m, u; 21 scanf("%d%d", &n, &m); 22 for(int i = 1; i <= m; i++){ 23 scanf("%d", &u); 24 cnt[u]++; 25 } 26 for(int i = m; i >= 1; i--){ 27 int tot = 0; 28 for(int j = 1; j <= 100; j++) 29 tot += cnt[j]/i; 30 if(tot >= n) { 31 printf("%d\n", i); 32 return 0; 33 } 34 } 35 puts("0"); 36 return 0; 37 }
题意:
现在有1-n, n个星球, 现在某个人要按 1 -> 2 -> 3 -> 4 -> ... -> n -> 1的方式走完旅行, 他先再1号星球上起飞, 然后在2号星球降落, 再从2号星球起飞 ... 在n号星球降落,n号星球起飞, 1号星球降落。就完成了旅行。
每个星球有一个起飞系数 ai 有一个降落系数 bi, 每一 ton 燃料 可以带动 ai / bi 的重量的东西 起飞/降落, 现在他乘着 m ton的火箭, 然后问带最小多少 ton 的燃料可以完成旅行, 如果完成不了输出-1;。
题解:
听说好像是可以倒着模拟, 我觉得也是可以的。
我本人写的是2分, 2分燃料, 然后每次都check一下, 判断是否可以, 如果可以就减少燃料上限, 如果不行就增加燃料下限, 最后跑完2分之后在check一下燃料值, 如果可以就输出答案, 不行就输出-1。
代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define Fopen freopen("_in.txt","r",stdin); freopen("_out.txt","w",stdout); 4 #define LL long long 5 #define ULL unsigned LL 6 #define fi first 7 #define se second 8 #define pb push_back 9 #define lson l,m,rt<<1 10 #define rson m+1,r,rt<<1|1 11 #define max3(a,b,c) max(a,max(b,c)) 12 #define min3(a,b,c) min(a,min(b,c)) 13 typedef pair<int,int> pll; 14 const int inf = 0x3f3f3f3f; 15 const LL INF = 0x3f3f3f3f3f3f3f3f; 16 const LL mod = (int)1e9+7; 17 const int N = 1e5 + 10; 18 double eps = 1e-8; 19 int a[N], b[N]; 20 int n, m; 21 bool check(double mm){ 22 double weight = mm + m; 23 double need; 24 for(int i = 1; i <= n; i++){ 25 need = (mm+m)/a[i]; 26 if(need > mm) return false; 27 mm -= need; 28 need = (mm+m)/b[i]; 29 if(need > mm) return false; 30 mm -= need; 31 } 32 return true; 33 } 34 int main(){ 35 scanf("%d%d", &n, &m); 36 for(int i = 1; i <= n; i++) 37 scanf("%d", &a[i]); 38 scanf("%d", &b[n]); 39 for(int i = 1; i < n; i++) 40 scanf("%d", &b[i]); 41 double l = 0, r = 2e9, mm ; 42 for(int i = 1; i <= 100; i++){ 43 mm = (l+r) / 2; 44 if(check(mm)) r = mm; 45 else l = mm; 46 } 47 if(check(r)) printf("%.8f", r); 48 else printf("-1"); 49 return 0; 50 }
交互题
题意:
某个人在地球去火星的路上,这段路程为 m , 现在他想知道有他现在离火星的距离是多少,他可以向火箭猜测现在他与火星的距离是多少,假设实际距离为 x ,现在他猜了y ,如果 y > x 则 火箭会返回 -1,如果 x == y 火箭会返0 , y < x 火箭会返回1 。但是火箭回答程序有一些损坏,有时候会回答出相反的答案, 即正确答案为1 他会返回 -1,0 返回0 ,-1返回1。 但是火箭回答正确与否是有周期的, 周期为n。 现在你最多询问60次, 要求输出正确的 x 值是多少。
题解:因为n最多30, 我们可以在第一段周期都输入0, 如果返回0, 那么说名实际距离就是0,否则的话, 那么实际距离一定 > 1, 那么我们就可以知道回答问题正确和相反是按照哪个周期了。接下来我们2分答案就好了。
注意的就是找到答案的时候要及时退出,并且输出的时候要换行。
代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define Fopen freopen("_in.txt","r",stdin); freopen("_out.txt","w",stdout); 4 #define LL long long 5 #define ULL unsigned LL 6 #define fi first 7 #define se second 8 #define pb push_back 9 #define lson l,m,rt<<1 10 #define rson m+1,r,rt<<1|1 11 #define max3(a,b,c) max(a,max(b,c)) 12 #define min3(a,b,c) min(a,min(b,c)) 13 typedef pair<int,int> pll; 14 const int inf = 0x3f3f3f3f; 15 const LL INF = 0x3f3f3f3f3f3f3f3f; 16 const LL mod = (int)1e9+7; 17 const int N = 1e5 + 100; 18 int a[N]; 19 int main(){ 20 int m, n; 21 scanf("%d%d", &m, &n); 22 for(int i = 1; i <= n; i++){ 23 printf("1\n"); 24 fflush(stdout); 25 scanf("%d", &a[i]); 26 if(a[i] == 0){ 27 printf("%d\n", 1); 28 exit(0); 29 } 30 } 31 for(int i = 1; i <= n; i++) 32 a[i] *= -1; 33 int cnt = 1; 34 int l = 2, r = m+1, mid; 35 int t; 36 while(1){ 37 mid = l+r >> 1; 38 printf("%d\n", mid); 39 fflush(stdout); 40 scanf("%d", &t); 41 if(t == 0) { 42 printf("%d\n", mid); 43 exit(0); 44 } 45 t *= a[cnt]; 46 cnt++; 47 if(cnt > n) cnt = 1; 48 if(t < 0) l = mid; 49 else r = mid; 50 } 51 return 0; 52 }
题意:
某个人去火星旅游,但是去火星旅游需要缴入门费,火星上的货币是以k进制进行的,并且火星上的人觉得 d 数字是神圣的,如果入门费的最后一位的数字是 d (基于k进制)那么火星人就会很开心,不幸的是我们不知道火星人觉得哪个数字是神圣的, 现在有 n 种面值为 ai 的货币(基于10进制), 每种货币都有有无穷个, 现在问在任意组合下, 最后能组合出多少个不同的最后一位的数字, 并且按大小输出所有的可以组成的数。
题解:
ax + by = z
如果给定a,b,z之后该方程有解, 那么 z % gcd(a,b) == 0, 所以我们求出所有面值关于k的 gcd 以及 所有面值之间的 gcd, 那么所有这些gcd倍数的值都可以被表示出来。
代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define Fopen freopen("_in.txt","r",stdin); freopen("_out.txt","w",stdout); 4 #define LL long long 5 #define ULL unsigned LL 6 #define fi first 7 #define se second 8 #define pb push_back 9 #define lson l,m,rt<<1 10 #define rson m+1,r,rt<<1|1 11 #define max3(a,b,c) max(a,max(b,c)) 12 #define min3(a,b,c) min(a,min(b,c)) 13 typedef pair<int,int> pll; 14 const int inf = 0x3f3f3f3f; 15 const LL INF = 0x3f3f3f3f3f3f3f3f; 16 const LL mod = (int)1e9+7; 17 const int N = 1e5 + 100; 18 int a[N]; 19 int vis[N]; 20 int cnt = 0; 21 int main(){ 22 int n, k; 23 scanf("%d%d", &n, &k); 24 int last = k; 25 for(int i = 1; i <= n; i++){ 26 scanf("%d", &a[i]); 27 a[i] %= k; 28 if(a[i]){ 29 last = __gcd(a[i], last); 30 a[i] = __gcd(a[i], k); 31 vis[a[i]] = 1; 32 } 33 else vis[0] = 1; 34 } 35 vis[last] = 1; 36 for(int i = 1; i < k; i++){ 37 if(vis[i]){ 38 cnt++; 39 for(int j = i*2; j <= k; j+=i) 40 vis[j] = 1; 41 } 42 } 43 vis[0] |= vis[k]; 44 if(vis[0]) cnt++; 45 printf("%d\n", cnt); 46 for(int i = 0; i < k; i++){ 47 if(vis[i]) printf("%d ", i); 48 } 49 return 0; 50 }
题意:一道模拟门电路的题。题目要求输出每个信号输入的位置取反之后最后 1 号位置的值是多少。
题解:先模拟出最开始的型号,并且处理出如果上一个位置的状态发生改变该位置的信号会不会发生改变,如果会发生改变,就标记一下上一个位置, 最后先dfs完一遍之后,就可以处理出每个位置发生改变之后会不会导致下一个位置的信息发生改变。 我们再从1号节点遍历一遍, 如果某个位置没有被标记过, 那么就清除他所有子节点的标记。
代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define Fopen freopen("_in.txt","r",stdin); freopen("_out.txt","w",stdout); 4 #define LL long long 5 #define ULL unsigned LL 6 #define fi first 7 #define se second 8 #define pb push_back 9 #define lson l,m,rt<<1 10 #define rson m+1,r,rt<<1|1 11 #define max3(a,b,c) max(a,max(b,c)) 12 #define min3(a,b,c) min(a,min(b,c)) 13 typedef pair<int,int> pll; 14 const int inf = 0x3f3f3f3f; 15 const LL INF = 0x3f3f3f3f3f3f3f3f; 16 const LL mod = (int)1e9+7; 17 const int N = 1e6 + 100; 18 int n; 19 int op[N];/// 1 -> & 2 -> ^ 3 -> not 4 -> in 20 int ok[N]; 21 int val[N]; 22 int ans[2]; 23 char s[10]; 24 vector<int> son[N]; 25 void dfs(int u){ 26 if(op[u] == 4) return ; 27 for(int i = 0; i < son[u].size(); i++) dfs(son[u][i]); 28 int x = son[u][0]; 29 if(op[u] == 3){ 30 val[u] = 1 ^ val[x]; 31 ok[x] = 1; 32 } 33 int y = son[u][1]; 34 if(op[u] == 1){ 35 val[u] = val[x] & val[y]; 36 if(val[y] == 1) ok[x] = 1; 37 if(val[x] == 1) ok[y] = 1; 38 } 39 else if(op[u] == 2){ 40 val[u] = val[x] ^ val[y]; 41 ok[x] = ok[y] = 1; 42 } 43 else if(op[u] == 5){ 44 val[u] = val[x] | val[y]; 45 if(val[x] == 1 && val[y] == 0) ok[x] = 1; 46 if(val[x] == 0 && val[y] == 1) ok[y] = 1; 47 if(val[x] == 0 && val[y] == 0) ok[x] = ok[y] = 1; 48 } 49 } 50 void dfs2(int u, int flag){ 51 ok[u] &= flag; 52 for(int i = 0; i < son[u].size(); i++) 53 dfs2(son[u][i], ok[u]); 54 } 55 int main(){ 56 scanf("%d", &n); 57 int u, v; 58 for(int i = 1; i <= n; i++){ 59 scanf("%s", s+1); 60 if(s[1] == 'I') op[i] = 4, scanf("%d", &val[i]); 61 else if(s[1] == 'N'){ 62 scanf("%d", &u); 63 son[i].pb(u); 64 op[i] = 3; 65 } 66 else { 67 scanf("%d%d", &u, &v); 68 son[i].pb(u); son[i].pb(v); 69 if(s[1] == 'A') op[i] = 1; 70 if(s[1] == 'X') op[i] = 2; 71 if(s[1] == 'O') op[i] = 5; 72 } 73 } 74 dfs(1); 75 ok[1] = 1; 76 dfs2(1,1); 77 ans[0] = val[1]; ans[1] = val[1] ^ 1; 78 for(int i = 1; i <= n; i++) 79 if(op[i] == 4) printf("%d", ans[ok[i]]); 80 return 0; 81 }