題面描述:能夠跳過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