p2456二進制方程 題解

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

第四行:等式右邊的表達式。

輸出格式

等式中出現的變量共有多少組解。

輸入輸出樣例

輸入 #1
2
4 2
1b1
a
輸出 #1
4
輸入 #2
5
4 2 4 4 2
1bad1
acbe
輸出 #2
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

相關文章
相關標籤/搜索