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

Input

The first line contains a string

The second line contains a string

It is guaranteed, that the string

Output

Print a single integer — the number of pairs of strings

In case there are no such pairs, print

Examples
Input
01
aaaaaa
Output
4
Input
001
kokokokotlin
Output
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
",ans);
    return 0;
}
View Code

版本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
",ans);
    return 0;
}
View Code

以及各种换种子; 一个用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
",ans);
    return 0;
}
原文地址:https://www.cnblogs.com/hua-dong/p/10030620.html