正手一个[南猪入侵],反手一个[万箭齐发],我的[桃]真的快用完了……OI啊(MP),我(ZP)劝你出手前考虑一下,如果我DEAD了,你可就没牌了……话说难道我没有跳过忠吗??
问题 A: 【2022NOIP联测4 10月6日】字符串还原
string用熟了,于是就忘了它的时间复杂度,TLE 40 不过用起来是真的简单,10分钟不到就搞定了。
#include <bits/stdc++.h> using namespace std; int n, mid, flag; string ans, u; inline int read() { int x = 0, f = 1; char ch = getchar(); while(ch < '0' || ch > '9') { if(ch == '-') { f = -1; } ch = getchar(); } while(ch >= '0' && ch <= '9') { x = (x << 1) + (x << 3) + (ch^48); ch = getchar(); } return x * f; } int main() { n = read(); mid = n/2; cin >> u; for(int i=1; i<n-1; i++) { string t = u.substr(0, i) + u.substr(i+1); string s1 = t.substr(0, mid), s2 = t.substr(mid); if(s1 == s2) { if(!flag) {ans = s1; flag++;} else flag++; } } string t = u.substr(1); string s1 = t.substr(0, mid), s2 = t.substr(mid); if(s1 == s2) { if(!flag) {ans = s1; flag++;} else flag++; } t.clear(); s1.clear(); s2.clear(); t = u.substr(0, n-1); s1 = t.substr(0, mid); s2 = t.substr(mid); if(s1 == s2) { if(!flag) {ans = s1; flag++;} else flag++; } if(flag > 1) printf("NOT UNIQUE\n"); else if(!flag) printf("NOT POSSIBLE\n"); else cout << ans << endl; return 0; }View Code
于是开始改hash,套用原来的string,TLE 95是因为每次答案的hash值我居然又拿出个string计算了一下。
#include <bits/stdc++.h> using namespace std; typedef unsigned long long ll; const int maxn = 2e6 + 30; int n, mid, flag; //ll mod = 1234567891; ll f[maxn], m[maxn], B = 131, lstans, nowans; string ans, u; inline int read() { int x = 0, f = 1; char ch = getchar(); while(ch < '0' || ch > '9') { if(ch == '-') { f = -1; } ch = getchar(); } while(ch >= '0' && ch <= '9') { x = (x << 1) + (x << 3) + (ch^48); ch = getchar(); } return x * f; } int main() { n = read(); mid = n/2; cin >> u; m[0] = 1; for(int i=1; i<=n; i++) m[i] = m[i-1] * B; n = u.length(); f[0] = u[0] - 'A' + 1; for(int i=1; i<n; i++) { f[i] = f[i-1] * B + (u[i]-'A'+1); } for(int i=1; i<=mid; i++) { ll h1 = f[i-1]*m[mid-i]+f[mid]-f[i]*m[mid-i]; ll h2 = f[n-1]-f[mid]*m[n-mid-1]; if(h1 == h2) { if(!flag) { string t = u.substr(0, i) + u.substr(i+1); string s1 = t.substr(0, mid), s2 = t.substr(mid); ans = s1; flag++; for(int i=0; i<ans.length(); i++) { lstans = lstans * B + (ans[i]-'A'+1); } } else { string t = u.substr(0, i) + u.substr(i+1); string s1 = t.substr(0, mid), s2 = t.substr(mid); nowans = 0; for(int i=0; i<s1.length(); i++) { nowans = nowans * B + (s1[i]-'A'+1); } if(nowans == lstans) continue; else { printf("NOT UNIQUE\n"); exit(0); } } } } for(int i=mid+1; i<n-1; i++) { ll h1 = f[mid-1]; ll h2 = f[n-1]-f[i]*m[n-i-1]+(f[i-1]-f[mid-1]*m[i-mid])*m[n-i-1]; if(h1 == h2) { if(!flag) { string t = u.substr(0, i) + u.substr(i+1); string s1 = t.substr(0, mid), s2 = t.substr(mid); ans = s1; flag++; for(int i=0; i<ans.length(); i++) { lstans = lstans * B + (ans[i]-'A'+1); } } else { string t = u.substr(0, i) + u.substr(i+1); string s1 = t.substr(0, mid), s2 = t.substr(mid); nowans = 0; for(int i=0; i<s1.length(); i++) { nowans = nowans * B + (s1[i]-'A'+1); } if(nowans == lstans) continue; else { printf("NOT UNIQUE\n"); exit(0); } } } } ll h1 = f[mid]-f[0]*m[mid], h2 = f[n-1]-f[mid]*m[mid]; if(h1 == h2) { if(!flag) { string t = u.substr(1); string s1 = t.substr(0, mid), s2 = t.substr(mid); ans = s1; flag++; for(int i=0; i<ans.length(); i++) { lstans = lstans * B + (ans[i]-'A'+1); } } else { string t = u.substr(1); string s1 = t.substr(0, mid), s2 = t.substr(mid); nowans = 0; for(int i=0; i<s1.length(); i++) { nowans = nowans * B + (s1[i]-'A'+1); } if(nowans != lstans) { printf("NOT UNIQUE\n"); exit(0); } } } h1 = f[mid-1]; h2 = f[n-2]-f[mid-1]*m[mid]; if(h1 == h2) { if(!flag) { string t = u.substr(0, n-1); string s1 = t.substr(0, mid), s2 = t.substr(mid); ans = s1; flag++; for(int i=0; i<ans.length(); i++) { lstans = lstans * B + (ans[i]-'A'+1); } } else { string t = u.substr(0, n-1); string s1 = t.substr(0, mid), s2 = t.substr(mid); nowans = 0; for(int i=0; i<s1.length(); i++) { nowans = nowans * B + (s1[i]-'A'+1); } if(nowans != lstans) { printf("NOT UNIQUE\n"); exit(0); } } } if(!flag) printf("NOT POSSIBLE\n"); else cout << ans << endl; return 0; }View Code
由分类讨论发现得到答案并不需要两个中转string,可以直接拿,并且发现答案的hash已经记录过,然后A个T1居然花了一下午!?
#include <bits/stdc++.h> using namespace std; typedef unsigned long long ll; const int maxn = 2e6 + 30; int n, mid, flag; //ll mod = 1234567891; ll f[maxn], m[maxn], B = 131, lstans, nowans; string ans, u; inline int read() { int x = 0, f = 1; char ch = getchar(); while(ch < '0' || ch > '9') { if(ch == '-') { f = -1; } ch = getchar(); } while(ch >= '0' && ch <= '9') { x = (x << 1) + (x << 3) + (ch^48); ch = getchar(); } return x * f; } int main() { n = read(); mid = n/2; cin >> u; m[0] = 1; for(int i=1; i<=n; i++) m[i] = m[i-1] * B; n = u.length(); f[0] = u[0] - 'A' + 1; for(int i=1; i<n; i++) { f[i] = f[i-1] * B + (u[i]-'A'+1); } for(int i=1; i<=mid; i++) { ll h1 = f[i-1]*m[mid-i]+f[mid]-f[i]*m[mid-i]; ll h2 = f[n-1]-f[mid]*m[n-mid-1]; if(h1 == h2) { if(!flag) { string s1 = u.substr(mid+1); ans = s1; flag++; lstans = h1; } else { nowans = h1; if(nowans == lstans) continue; else { printf("NOT UNIQUE\n"); exit(0); } } } } for(int i=mid+1; i<n-1; i++) { ll h1 = f[mid-1]; ll h2 = f[n-1]-f[i]*m[n-i-1]+(f[i-1]-f[mid-1]*m[i-mid])*m[n-i-1]; if(h1 == h2) { if(!flag) { string s1 = u.substr(0, mid); ans = s1; flag++; lstans = h1; } else { nowans = h1; if(nowans == lstans) continue; else { printf("NOT UNIQUE\n"); exit(0); } } } } ll h1 = f[mid]-f[0]*m[mid], h2 = f[n-1]-f[mid]*m[mid]; if(h1 == h2) { if(!flag) { string s1 = u.substr(mid+1); ans = s1; flag++; lstans = h1; } else { nowans = h1; if(nowans != lstans) { printf("NOT UNIQUE\n"); exit(0); } } } h1 = f[mid-1]; h2 = f[n-2]-f[mid-1]*m[mid]; if(h1 == h2) { if(!flag) { string s1 = u.substr(0, mid); ans = s1; flag++; lstans = h1; } else { nowans = h1; if(nowans != lstans) { printf("NOT UNIQUE\n"); exit(0); } } } if(!flag) printf("NOT POSSIBLE\n"); else cout << ans << endl; return 0; }View Code
注意事项就是判断重复是作为答案的字符串不能重复,而不是断点必须取同一个,感谢cr的提醒。我本来以为自动溢出会被卡的,毕竟大佬们都在用双模数,然而居然没卡我qwq
标签:ch,2022NOIPA,string,int,ll,while,联测,getchar From: https://www.cnblogs.com/Catherine2006/p/16758108.html