CF1056:Check Transcription(被hack的hash)
One of Arkady's friends works at a huge radio telescope. A few decades ago the telescope has sent a signal
The original signal
Please help Arkady's friend and find the number of possible replacements for zeros and ones (the number of pairs of strings
InputThe first line contains a string
The second line contains a string
It is guaranteed, that the string
OutputPrint a single integer — the number of pairs of strings
In case there are no such pairs, print
Examples01 aaaaaa
4
001 kokokokotlin
2
题意:给定一个01串S,和一个字符串T,然后问有多少种方案,使得0和1分别代表一段不同的字符串,使得S==T。
思路:假设S中0的个数的B,1的个数是A,那么就是问多少解Ax+By=C;枚举x,然后hash验证即可。
这里写了几个版本都WA17了。
版本1:双hash,用unsigned int自然溢出。
#include<bits/stdc++.h> #define ui unsigned int #define pii pair<ui,ui> #define F first #define S second #define rep(i,a,b) for(int i=a;i<=b;i++) using namespace std; const int maxn=1000010; const int seed1=131; const int seed2=1331; char a[maxn],b[maxn]; pii p[maxn],Hash[maxn]; int A,B; int main() { int N,M,ans=0; scanf("%s%s",a+1,b+1); N=strlen(a+1); M=strlen(b+1); rep(i,1,N) if(a[i]=='1') A++;else B++; p[0].F=p[0].S=1; rep(i,1,M) p[i].F=p[i-1].F*seed1,p[i].S=p[i-1].S*seed2; Hash[0].F=Hash[0].S=1;rep(i,1,M) Hash[i].F=Hash[i-1].F*seed1+b[i],Hash[i].S=Hash[i-1].S*seed2+b[i]; rep(i,1,M/A){ int x=i,y=(M-x*A)/B; bool F=true; if(y<1||x*A+y*B!=M) continue; int vis1=-1,vis0=-1,pos=1; pii tag0,tag1; rep(j,1,N){ if(a[j]=='1') { int To=pos+x-1; pii tmp; tmp.F=Hash[To].F-Hash[pos-1].F*p[x].F; tmp.S=Hash[To].S-Hash[pos-1].S*p[x].S; if(vis1==-1) vis1=1,tag1=tmp; else if(tmp!=tag1) {F=false; break;} pos=To+1; } else { int To=pos+y-1; pii tmp; tmp.F=Hash[To].F-Hash[pos-1].F*p[y].F; tmp.S=Hash[To].S-Hash[pos-1].S*p[y].S; if(vis0==-1) vis0=1,tag0=tmp; else if(tmp!=tag0) {F=false; break;} pos=To+1; } } if(tag0!=tag1&&F) ans++; } printf("%d\n",ans); return 0; }
版本2:双hash,用unsigned long long自然溢出
#include<bits/stdc++.h> #define ui unsigned long long #define pii pair<ui,ui> #define F first #define S second #define rep(i,a,b) for(int i=a;i<=b;i++) using namespace std; const int maxn=1000010; const ui seed1=131; const ui seed2=133131; char a[maxn],b[maxn]; pii p[maxn],Hash[maxn]; int A,B; int main() { int N,M,ans=0; scanf("%s%s",a+1,b+1); N=strlen(a+1); M=strlen(b+1); rep(i,1,N) if(a[i]=='1') A++; else B++; p[0].F=p[0].S=1; rep(i,1,M) p[i].F=p[i-1].F*seed1,p[i].S=p[i-1].S*seed2; Hash[0].F=Hash[0].S=1;rep(i,1,M) Hash[i].F=Hash[i-1].F*seed1+b[i],Hash[i].S=Hash[i-1].S*seed2+b[i]; rep(i,1,M/A){ int x=i,y=(M-x*A)/B; bool Flag=true; if(y<1||x*A+y*B!=M) continue; int vis1=-1,vis0=-1,pos=1; pii tag0,tag1; rep(j,1,N){ if(a[j]=='1') { int To=pos+x-1; pii tmp; tmp.F=Hash[To].F-Hash[pos-1].F*p[x].F; tmp.S=Hash[To].S-Hash[pos-1].S*p[x].S; if(vis1==-1) vis1=1,tag1=tmp; else if(tmp!=tag1) {Flag=false; break;} pos=To+1; } else { int To=pos+y-1; pii tmp; tmp.F=Hash[To].F-Hash[pos-1].F*p[y].F; tmp.S=Hash[To].S-Hash[pos-1].S*p[y].S; if(vis0==-1) vis0=1,tag0=tmp; else if(tmp!=tag0) {Flag=false; break;} pos=To+1; } } if(tag0!=tag1&&Flag) ans++; } printf("%d\n",ans); return 0; }
以及各种换种子; 一个用uint,一个用ull; hash时一个直接加,一个加a-48;都是WA。
https://codeforces.com/blog/entry/4898
这里介绍了自然溢出容易被hack,和种子无关。%质数比较保险。 改一下就AC了。以后再也不自然溢出了。
#include<bits/stdc++.h> #define ui long long #define ul long long #define pii pair<ui,ul> #define F first #define S second #define rep(i,a,b) for(int i=a;i<=b;i++) using namespace std; const int maxn=1000010; const ui seed1=131; const ul seed2=1331; char a[maxn],b[maxn]; const ui Mod=1e9+7; pii p[maxn],Hash[maxn]; int A,B; int main() { int N,M,ans=0; scanf("%s%s",a+1,b+1); N=strlen(a+1); M=strlen(b+1); rep(i,1,N) if(a[i]=='1') A++; else B++; p[0].F=p[0].S=1; rep(i,1,M) p[i].F=p[i-1].F*seed1%Mod,p[i].S=p[i-1].S*seed2%Mod; Hash[0].F=Hash[0].S=1;rep(i,1,M) Hash[i].F=(Hash[i-1].F*seed1%Mod+b[i])%Mod,Hash[i].S=(Hash[i-1].S*seed2%Mod+b[i])%Mod; rep(i,1,M/A){ int x=i,y=(M-x*A)/B; bool Flag=true; if(y<1||x*A+y*B!=M) continue; int vis1=-1,vis0=-1,pos=1; pii tag0,tag1; rep(j,1,N){ if(a[j]=='1') { int To=pos+x-1; pii tmp; tmp.F=((Hash[To].F-Hash[pos-1].F*p[x].F%Mod)%Mod+Mod)%Mod; tmp.F=((Hash[To].S-Hash[pos-1].S*p[x].S%Mod)%Mod+Mod)%Mod; if(vis1==-1) vis1=1,tag1=tmp; else if(tmp!=tag1) {Flag=false; break;} pos=To+1; } else { int To=pos+y-1; pii tmp; tmp.F=((Hash[To].F-Hash[pos-1].F*p[y].F%Mod)%Mod+Mod)%Mod; tmp.F=((Hash[To].S-Hash[pos-1].S*p[y].S%Mod)%Mod+Mod)%Mod; if(vis0==-1) vis0=1,tag0=tmp; else if(tmp!=tag0) {Flag=false; break;} pos=To+1; } } if(tag0!=tag1&&Flag) ans++; } printf("%d\n",ans); return 0; }