代码等式

来源:互联网 发布:adobe cc 2017 mac破解 编辑:程序博客网 时间:2024/04/27 20:27

Description

有一个二进制码。不过你得到的是“加密”的代码,有几个连续的数字(0或1)合为了一个长度一定的变量,你得到了两条本来相同加密方式不同的代码(代码中包含变量)以及变量的长度,求原代码可能的个数。

Input

第一行一个正整数T(1<=T<=2)表示共有T组数据每组数据输入共6行:第一行一个正整数n(0<=n<=26),表示变量的个数(变量用abcdefg..这样连续的小写英文表示)第二行一共n个正整数(X1,X2,X3...),每一个数字Xi(0<=Xi<=10000)表示一个变量的长度(X1表示变量a的长度;X2表示变量b的长度;X3表示变量c的长度...)第三行一个正整数length1(1<=lenght1<=5000),表示第一条代码的长度第四行一个长度为length1的字符串,表示第一条代码第五行一个正整数length2(1<=length2<=5000),表示第二条代码的长度第六行一个长度为length2的字符串,表示第二条代码

Output

共T行,每一行一个整数,表示原代码可能的个数

Sample Input

154 2 4 4 251bad14acbe

Sample Output

16

分析

我们把式子打开,得到“a1a21b1b2”,“b1b2c1c2c3”,题目要求是对应位置上的相等。我们可以把每个元素看做一个点,在对应位置上的连一条边(比如a1和b1有一条边,1和c1有一条边),那么可以形成一些联通块,每个联通块互不影响,所以答案就是2^p(p是联通块个数,不过不能算那些包含0或者是1的联通块),因为每一个联通块里都可以是0或者是1(不包括那些包含0或者是1联通块)故由乘法原理我们可以知道答案就是2^p.

代码

#include <cstdio>#include <cstring>#include <algorithm>using namespace std;int a[27][10010];int fa[274700];int n;int len[27];char str1[4700];int len1;char str2[4700];int tmp[470000];int len2;int r;int ans[470000];int k;int tot;int fin(int);void uni(int,int);void mi(int);int main(){    scanf("%d",&r);    while(r--){        scanf("%d",&n);        for(int i=0;i<n;++i)            scanf("%d",len+i);        scanf("%d%s%d%s",&len1,str1,&len2,str2);        int len_tr = 0;        for(int i=0;i<len1;++i)            if(str1[i]=='0' || str1[i]=='1')                ++len_tr;            else                len_tr += len[str1[i]-'a'];        for(int i=0;i<len2;++i)            if(str2[i]=='0' || str2[i]=='1')                --len_tr;            else                len_tr -= len[str2[i]-'a'];        if(len_tr){            printf("0\n");            goto go_next_loop;        }        tot = 1;        for(int i=0;i<n;++i)            for(int j=1;j<=len[i];++j)                a[i][j] = ++tot;        for(int i=0;i<=tot;++i)            fa[i] = i;        for(int i=0,x=0,y=1,p=0,q=1;x<len1&&p<len2;++i){            if(str1[x]==str2[p] && (str1[x]=='0'||str1[x]=='1')){                x++,p++,y=q=1;                continue;            }            else if((str1[x]=='0'&&str2[p]=='1') || (str1[x]=='1'&&str2[p]=='0')){                printf("0\n");                goto go_next_loop;            }            else if(str1[x]=='0' || str1[x]=='1'){                uni(str1[x]-'0',a[str2[p]-'a'][q]);                x++,y=1,q++;            }            else if(str2[p]=='0' || str2[p]=='1'){                uni(str2[p]-'0',a[str1[x]-'a'][y]);                p++,q=1,y++;            }            else{                uni(a[str1[x]-'a'][y],a[str2[p]-'a'][q]);                y++,q++;            }            if(y > len[str1[x]-'a'])                x++,y=1;            if(q > len[str2[p]-'a'])                p++,q=1;        }        if(fin(0) == fin(1)){            printf("0\n");            goto go_next_loop;        }        k = 0;        for(int i=0;i<=tot;++i)            if(fa[i] == i)                ++k;        memset(ans,0,sizeof ans);        mi(k-2);        for(int i=ans[0];i>=1;--i)            printf("%d",ans[i]);        putchar(10);    go_next_loop:;    }    return 0;}int fin(int x){    int r = x,q;    while(r != fa[r])        r = fa[r];    while(x != fa[x]){        q = fa[x];        fa[x] = r;        x = q;    }    return r;}void uni(int x,int y){    fa[fin(x)] = fin(y);}void mi(int p){    if(p == 1){        ans[0] = 1;        ans[1] = 2;        return ;    }    if(p == 0){        ans[0] = 1;        ans[1] = 1;        return ;    }    mi(p/2);    memset(tmp,0,sizeof tmp);    for(int i=1;i<=ans[0];++i)        for(int j=1;j<=ans[0];++j)            tmp[i+j-1] += ans[i]*ans[j];    if(p&1)        for(int i=1;i<=(ans[0]<<1)-1;++i)            tmp[i] <<= 1;    for(int i=2;i<=(ans[0]<<1);++i){        tmp[i] += tmp[i-1]/10;        tmp[i-1] %= 10;    }    ans[0] <<= 1;    if(!tmp[ans[0]])        ans[0] -= 1;    for(int i=1;i<=ans[0];++i)        ans[i] = tmp[i];}
0 0
原创粉丝点击