2016-2017 ACM-ICPC (SEERC 2016) 【solved:7 / 11】
来源:互联网 发布:电脑怎么用手机网络 编辑:程序博客网 时间:2024/06/11 18:15
剩下的都没题解了。可做一点的怕是只有A和J了。
-update : 2017年10月9日21:43:43
C - Castle(kmp的next数组的应用)
题意:给出原串s,然后有3种操作,1、在s的末尾加上一个小写字母ch;2、把s的拷贝放入set;3、询问在set中的字符串是当前字符串s‘的后缀的个数。
思路:
我们考虑到kmp中,next[i]的意义是,i这个前缀串中。它自己的前缀和自己的后缀的最长公共部分。
首先毫无疑问我们要维护整个字符串的next数组。然后我们去dp,每次加入一个新的字符s[i]的时候,显然可以得知目前ans[i] = ans[pre[i]] 。然后如果再把这个前缀i第一次插到集合set里面的时候,显然ans[i]++,且只会加一次,因为是个set。需要打个vis标记一下。就可以得到答案了
#include <bits/stdc++.h>using namespace std;const int maxn = 2000000 + 5;char s[maxn];int pre[maxn], ans[maxn], vis[maxn];int main(){ int n, E; scanf("%d%d", &n, &E); getchar(); gets(s + 1); int j = 0; for(int i = 2; i <= n; i++) { while(j && s[j + 1] != s[i]) j = pre[j]; if(s[j + 1] == s[i]) j++; pre[i] = j; } int idx = n; while(E--) { int op; scanf("%d", &op); if(op == 1) { scanf(" %c", &s[++idx]); while(j && s[j + 1] != s[idx]) j = pre[j]; if(s[j + 1] == s[idx]) j++; pre[idx] = j; ans[idx] = ans[j]; } else if(op == 2) { if(vis[idx] == 0) ans[idx]++, vis[idx] = 1; } else if(op == 3) { printf("%d\n", ans[idx]); } } return 0;}
D - Reading Digits (简单模拟)
题意:有一种加密方式:1211->111221->312211。现在告诉你加密k次后的字符串,问你原串的第pos位是什么数字。(
k≤40,pos≤1e5 )
#include <bits/stdc++.h>using namespace std;int main(){ int k, pos; scanf("%d%d", &k, &pos); string s; cin >> s; while(k--) { string temp = ""; for(int i = 0; i < s.size(); i += 2) { int times = s[i] - '0'; while(times--) temp += s[i + 1]; } s = temp; } printf("%c\n", s[pos]); return 0;}
F - Letters (小模拟进制转换)
题意:有一个
ABC⋯XYZAAABAC⋯AXAYAZ 的序列,现在问你第n项是什么字符。例如第0项是A, 第25项是Z。
思路:A-Z:长度为1,有26个。AA-ZZ:长度为2,有26*26个。所以容易求出第n个字符所属于的那部分长度是len。然后会令group = delta/len,会得到你要找的数字属于哪个串,比如“AAA”或者是“DEF”。然后你发现就是一个你要找的那个串就是group = delta/len这个数字的值的26进制表示方式。然后需要倒过来找一下即可。
思路:
#include <bits/stdc++.h>using namespace std;long long r26[10];int main(){ r26[0] = 1; for(int i = 1; i <= 7; i++) r26[i] = r26[i - 1] * 26; int idx; while(~scanf("%d", &idx)) { long long num = 0, len = 1; while(1) { long long cur = 1LL * len * r26[len]; if(num + cur <= idx) { num += cur; } else break; len++; } vector<int>ans; long long group = (idx - num) / len; long long id = (idx - num) % len; for(int i = 0, temp = group; i < len; i++) { ans.push_back(temp % 26); temp /= 26; } printf("%c\n", ans[len-1-id] + 'A'); } return 0;}
G - Pokemons (water)
题意:告诉你n天,每天货物的价格,你一开始拥有的金钱。你要买exactly一次货物。问你最后最多获利多少(可能为负数)
思路:除了卡内存,卡时限以外。就是个水题。
#include <bits/stdc++.h>using namespace std;int readInt() { int ret = 0; while(1) { char c = getchar(); if(c == ' ' || c == '\n') break; if('0' > c || c > '9') continue; ret *= 10; ret += c - '0'; } return ret;}double readFloat() { double ret = 0; double po = 1; bool nega = false; while(1) { char c = getchar(); if(c == ' ' || c == '\n') break; if(c == '-') { nega = true; continue; } if(c == '.') { po /= 10; continue; } if('0' > c || c > '9') continue; if(abs(po - 1) > 1e-9) { ret += po * (c - '0'); po /= 10; } else { ret *= 10; ret += c - '0'; } } return nega? -ret : ret;}int main(){ double st = readFloat(); int n = readInt(); double minPrice = readFloat(); double ans = 0; for(int i = 1; i < n; i++) { double cur = readFloat(); if(i == 1) ans = (cur - minPrice) * (st / minPrice); if(cur < minPrice) minPrice = cur; else ans = max(ans, (cur - minPrice) * (st / minPrice)); } printf("%.2f\n", ans); return 0;}
H - Pub crawl (凸包)
题意:给出若干个平面上的点,保证无三点共线,你每次都只能连上左边的点,问你最多能连几个点,给出连线顺序。(
N≤5000 )
思路:其实就是个不断做凸包的过程,把做过的点打个vis标记就行了。
关于复杂度的计算:《挑战》P261 3.6.4有个结论,凸包上的点是
#include <bits/stdc++.h>using namespace std;const int maxn = 5000 + 5;int vis[maxn];struct Point{ long long x, y; int idx; Point operator + (const Point &other)const{return {x+other.x, y+other.y};} Point operator - (const Point &other)const{return {x-other.x, y-other.y};} Point operator * (const Point &other)const{return {x*other.x, y*other.y};} bool operator < (const Point &other)const { if(x != other. x) return x < other.x; return y < other.y; }};double Cross(Point A, Point B){return A.x*B.y - A.y*B.x;}//返回向量A和向量B的叉积int ConvexHull(Point p[], int n, Point sta[]){//如果在凸包的边可以有输入点,则两个while里用<=0,否则使用<0。 sort(p, p + n); int m = 0; while(m < n) { for(int i = 0; i < n; i++) { if(vis[p[i].idx]) continue; while(m > 1 && Cross(sta[m-1] - sta[m-2], p[i] - sta[m-2]) < 0) { vis[sta[m-1].idx] = 0; m--; } sta[m++] = p[i]; vis[sta[m-1].idx] = 1; } int k = m; for(int i = n - 2; i >= 0; i --) { if(vis[p[i].idx]) continue; while(m > k && Cross(sta[m-1] - sta[m-2], p[i] - sta[m-2]) < 0) { vis[sta[m-1].idx] = 0; m--; } sta[m++] = p[i]; vis[sta[m-1].idx] = 1; } } if(n > 1) m--; return m;}Point nodes[maxn], sta[maxn];int main(){ int n; scanf("%d", &n); for(int i = 0; i < n; i++) { int x, y; scanf("%d%d", &x, &y); nodes[i] = {x, y, i + 1}; } ConvexHull(nodes, n, sta); printf("%d\n", n); for(int i = 0; i < n; i++) printf("%d%c", sta[i].idx, " \n"[i + 1 == n]); return 0;}
I - Cubes
题意:给你一个数字n,问它最少可以由几个3的幂加和得到。输出数量及方案。(
n≤44777444 )
思路:大力感知了一下,感觉最多只有十几个所以暴力搜一搜,玄学剪枝最为致命,剪枝很关键。其他就。随便爆搜吧。
#include <bits/stdc++.h>using namespace std;int a[200], ans[200], mi[400];int ans_num = 0x3f3f3f3f;void dfs(int n, int up, int num, int a[]){ if(num > 15) return; if(n == 0) { if(num < ans_num) { ans_num = num; for(int i = 0; i < num; i++) ans[i] = a[i]; } return ; } if(num + 1 >= ans_num) return; if(num + n / mi[up] >= ans_num) return; for(int i = up; i >= 1; i--) { if(mi[i] > n) continue; a[num] = i; dfs(n - mi[i], i, num+1, a); }}int main(){ int n; scanf("%d", &n); mi[0] = 1; for(int i = 1; i <= 356; i++) mi[i] = i * i * i; dfs(n, 356, 0, a); sort(a, a + ans_num); printf("%d\n", ans_num); for(int i = 0; i < ans_num; i++) { printf("%d%c", ans[i], " \n"[i + 1 == ans_num]); } return 0;}
K - Cutting (哈希+自然溢出)
题意:对于串 S1 和 S2,求一种将串 S1 任意分割为 3 个子串 A, B, C ,满足 A+B+C=S1,同时通过改变排序能构成 S2 串。串长5000.
思路:
枚举三段[0,i-1],[i,j-1],[j,len-1]。然后我们通过哈希检验即可。一开始采用的是longlong 和 mod。但是我们发现,会T。
可是如果我们改变思路,采用自然溢出,使用unsigned,采用自然溢出,不去取模。效率有极大的提升。
但是我们还是会T。是因为base取了26。取质数比较好。取29即可。
然后我们发现会WA,大概是还是有冲突?在哈希符合条件的时候,遍历一遍串,看看是否真的符合。
#include <bits/stdc++.h>using namespace std;const int maxn = 5000 + 5;const int base = 29;typedef unsigned long long LL;char str1[maxn], str2[maxn];unsigned int mi[maxn];unsigned int hashStr1[maxn];unsigned int hashOfStr2;unsigned int calc(unsigned int a, unsigned int b, unsigned int c, int len2, int len3){ return ((a * mi[len2] + b) * mi[len3] + c);}bool judge(int al, int ar, int bl, int br, int cl, int cr){ int st = 0; for(int i = 0; i < ar - al + 1; i++) { if(str2[st + i] != str1[al + i]) return false; } st += ar - al + 1; for(int i = 0; i < br - bl + 1; i++) { if(str2[st + i] != str1[bl + i]) return false; } st += br - bl + 1; for(int i = 0; i < cr - cl + 1; i++) { if(str2[st + i] != str1[cl + i]) return false; } return true;}void output(int i, int j){ puts("YES"); char ch = str1[i]; str1[i] = '\0'; puts(str1); str1[i] = ch; ch = str1[j]; str1[j] = '\0'; puts(str1+i); str1[j] = ch; puts(str1+j);}void solve(){ int len = strlen(str1); unsigned int a = str1[0] - 'a'; for(int i = 1; i < len; i++) { unsigned int b = str1[i] - 'a'; for(int j = i + 1; j < len; j++) { unsigned int c = hashStr1[j]; if(calc(a, b, c, j-i, len-j) == hashOfStr2 && judge(0, i-1, i, j-1, j, len-1)) {output(i, j);return ;} if(calc(a, c, b, len-j, j-i) == hashOfStr2 && judge(0, i-1, j, len-1, i, j-1)) {output(i, j);return ;} if(calc(b, a, c, i, len-j) == hashOfStr2 && judge(i, j-1, 0, i-1, j, len-1)) {output(i, j);return ;} if(calc(b, c, a, len-j, i) == hashOfStr2 && judge(i, j-1, j, len-1, 0, i-1)) {output(i, j);return ;} if(calc(c, a, b, i, j-i) == hashOfStr2 && judge(j, len-1, 0, i-1, i, j-1)) {output(i, j);return ;} if(calc(c, b, a, j-i, i) == hashOfStr2 && judge(j, len-1, i, j-1, 0, i-1)) {output(i, j);return ;} b = b * base + str1[j] - 'a'; } a = a * base + str1[i] - 'a'; } puts("NO"); return ;}int main(){ mi[0] = 1; for(int i = 1; i < maxn; i++) mi[i] = mi[i - 1] * base; scanf("%s", &str1); scanf("%s", &str2); int len = strlen(str2); hashOfStr2 = 0; for(int i = 0; i < len; i++) { hashOfStr2 = (hashOfStr2 * base + str2[i] - 'a'); } len = strlen(str1); hashStr1[len] = 0; for(int i = len - 1; i >= 0; i--) { hashStr1[i] = (str1[i] - 'a') * mi[len - 1 - i] + hashStr1[i + 1]; } solve(); return 0;}
- 2016-2017 ACM-ICPC (SEERC 2016) 【solved:7 / 11】
- 2016ACM/ICPC亚洲区大连站【solved:10 / 11】
- 2017 ACM/ICPC Asia Regional Qingdao Online【solved:7 / 11】
- 2016-2017 ACM-ICPC, Egyptian Collegiate Programming Contest (ECPC 16)【solved:9 / 11】
- 2016-2017 ACM-ICPC, NEERC, Central Subregional Contest【solved : 10 / 11】
- 2016ACM/ICPC亚洲区青岛站【solved:5 / 13】
- 2017 ACM/ICPC Asia Regional Shenyang Online【solved:7 / 12】
- 2016-2017 ACM-ICPC Pacific Northwest Regional Contest (Div. 2)【solved:12 / 13】
- 2016-2017 ACM-ICPC Pacific Northwest Regional Contest (Div. 1) 【solved:9 / 12】
- SEERC-2016
- 2017ACM/ICPC亚洲区沈阳站【solved:6 / 13】
- 【DP 训练】Alibaba, ACM/ICPC SEERC 2004, UVa1632
- 2017 ACM-ICPC 亚洲区(乌鲁木齐赛区)网络赛【solved:9 / 10】
- 2016 acm/icpc Qingdao
- 2015ACM/ICPC亚洲区长春站【solved:5 / 13】
- 2015ACM/ICPC亚洲区上海站【solved:4 / 12】
- 2016-2017 ACM-ICPC, NEERC, Central Subregional Contest【9/11】
- 2016-2017 ACM-ICPC CHINA-Final
- 可设RadioButton图片的大小
- 说明:最新"谷歌AI智商不超过6岁"研究来自科学院而非康内尔大学
- Boolan 设计模式 第二周
- 安装Gitlab
- dns命令详解
- 2016-2017 ACM-ICPC (SEERC 2016) 【solved:7 / 11】
- mysql学习
- LRUCache
- JavaWeb开发之路3
- 优化 shiro 多次调用 redis 的问题
- 使用Adobe Acrobat Pro制作带有表单的pdf
- 用户禁止cookie后,如何继续使用session
- 有哪些目前流行的前端框架
- Android Html设置TextView的颜色、加粗样式