zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    领域驱动设计实践,精通业务,面向对象编程,面条编程,过程编程
    日志聚合与全链路监控
    Spring Security OAuth2 之token 和 refresh token
    Web开发技术发展历程(笔记)
    JDBC 数据处理 总结
    Idea创建Maven多模块项目
    中国 / 省市区县 / 四级联动 / 地址选择器(京东商城地址选择)
    左膀mongostat,右臂mongotop——MongoDB的监控之道
    制定项目章程
    挣值分析
  • 原文地址:https://www.cnblogs.com/hua-dong/p/10030620.html
Copyright © 2011-2022 走看看