题面描述:能够跳过ios
一个形如:编程
X1X2…Xn=Y1Y2..Ym数组
的等式称为二进制方程。spa
在二进制方程的两边:Xi和Yj (1<=i<=n;1<=j<=m)是二进制数字(0、1)或者一个变量(小写字母)。每一个变量都是一个有固定长度的二进制代码,他能够在等式中取代变量的位置,称这个长度为变量的长度。为了解一个二进制方程,须要给其中的变量赋予适当的二进制代码,使得咱们用他们替代等式中的相应的变量后(等式的两边都变成二进制代码),这个等式成立。code
编程任务:orm
对于每个给出的方程,计算一共有多少组解。已知变量最多有26个(26个英文小写字母),且等式的每一端的数字和变量的长度之和不超过10000。blog
第一行:k(k<=26,变量的个数,规定使用小写英文字母中的前k个字母做为变量,如k=5,则变量a,b,c,d,e)。字符串
第二行:k个正整数,中间用一个空格隔开,依次表明k个变量的长度。input
第三行:等式左边的表达式。string
第四行:等式右边的表达式。
等式中出现的变量共有多少组解。
2 4 2 1b1 a
4
5 4 2 4 4 2 1bad1 acbe
16
样例一:4组解
1 、a=1001; b=00
二、 a=1011; b=01
三、 a=1101; b=10
四、 a=1111; b=11)
样例二:K=5,变量:a,b,c,d,e。长度分别为:4 2 4 4 2。等式是:1bad1= acbe
输出16,即变量a,b,c,d,e共有16组解。
(为何复制按钮还能粘贴上??(雾))
正解开始:
首先读懂题意咱们知道,每个字母都表明一个式子,且把每个字母替换成数字后可使得左右两个式子相等。
本人思路来源:先进行过样例式的枚举:
考虑这种状况:假如左边式子第1位是a,右边式子第一位是1,一个数字,一个字母,由于题意要知足对应位相等,因此咱们能够肯定字母a的第一位为1。可是,由于整个字符串中maybe有多个a,那么咱们找到字符串中的其余的a,把它们第一位对应的位数赋值为1.
然而a的第一位的对应位肯定,那么等号另外一边的对应位也能肯定了,而它又是一个字母,因而咱们把这个字母的对应位也找出来进行赋值。。。。。。这么下去,解法逐渐明朗:并查集。
具体来讲,咱们能够按照这种方法,把全部的能遍历到的位置按照并查集处理,并看作一种状况。最后,看还剩几种状况,咱们把答案高精度乘为2的几回方就OK了(由于每一位有0,1两种方法)qwq。
code:
#include<cstdio> #include<iostream> #include<algorithm> #include<cstring> using namespace std; const int maxn=10003; int n,m,k,sum; int num[maxn],fa[maxn],x[maxn],y[maxn]; inline int find(int x) { if(x==fa[x])return x; fa[x]=find(fa[x]); return fa[x]; } int main() { num[1]=2; scanf("%d",&k); for(int i=2,x;i<=k+1;++i) { scanf("%d",&x); num[i]=num[i-1]+x; sum+=x;//记录总不一样的个数 } char zfc[maxn]; scanf("%s",zfc); for(int i=0;zfc[i];++i) { if(zfc[i]>='a'&&zfc[i]<='z') { int c=zfc[i]-'a'+1;//获取他是num数组第几个 for(int j=num[c];j<num[c+1];++j)x[++n]=j;//按位置赋值 } else x[++n]=zfc[i]-'0';//数字的话 } scanf("%s",zfc); for(int i=0;zfc[i];++i) { if(zfc[i]>='a'&&zfc[i]<='z') { int c=zfc[i]-'a'+1; for(int j=num[c];j<num[c+1];++j)y[++m]=j;//字母 } else y[++m]=zfc[i]-'0';//数字 } if(n!=m)//连左右长度都不相等 { printf("0");return 0;//直接输出零 } for(int i=1;i<maxn;++i)fa[i]=i;//初始化并查集找父亲 for(int i=1;i<=n;++i) { int dx=find(x[i]),dy=find(y[i]); if(dx+dy==1) { printf("0"); return 0; } if(dx!=dy) { fa[max(dx,dy)]=min(dx,dy); sum--; } } int big[maxn]={1},top=1; for(int i=sum;i>=1;i--) { for(int i=0;i<top;++i)big[i]<<=1; for(int i=0;i<top;++i)if(big[i]>=10) { big[i+1]+=big[i]/10,big[i]%=10; } for(;big[top];++top) { big[top+1]+=big[top]/10,big[top]%=10; } } for(int i=top-1;i>=0;--i) printf("%d",big[i]); return 0; }
完结qwq