• p2456二进制方程 题解


    题面描述:可以跳过

    一个形如:

    X1X2…Xn=Y1Y2..Ym

    的等式称为二进制方程。

    在二进制方程的两边:Xi和Yj (1<=i<=n;1<=j<=m)是二进制数字(0、1)或者一个变量(小写字母)。每个变量都是一个有固定长度的二进制代码,他可以在等式中取代变量的位置,称这个长度为变量的长度。为了解一个二进制方程,需要给其中的变量赋予适当的二进制代码,使得我们用他们替代等式中的相应的变量后(等式的两边都变成二进制代码),这个等式成立。

    编程任务:

    对于每一个给出的方程,计算一共有多少组解。已知变量最多有26个(26个英文小写字母),且等式的每一端的数字和变量的长度之和不超过10000。

    输入格式

    第一行:k(k<=26,变量的个数,规定使用小写英文字母中的前k个字母作为变量,如k=5,则变量a,b,c,d,e)。

    第二行:k个正整数,中间用一个空格隔开,依次代表k个变量的长度。

    第三行:等式左边的表达式。

    第四行:等式右边的表达式。

    输出格式

    等式中出现的变量共有多少组解。

    输入输出样例

    输入 #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

    2、 a=1011; b=01

    3、 a=1101; b=10

    4、 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

  • 相关阅读:
    For-Each循环
    test
    网络学习一
    Struts2的interceptor
    Struts2的action解读
    js 读取<select>标签选项 索引
    java项目打jar包
    图解sendRedirect和forward的区别
    导入外部项目无法识别为Web项目无法部署到tomcat
    项目乱码的分析与解决
  • 原文地址:https://www.cnblogs.com/lbssxz/p/11355856.html
Copyright © 2020-2023  润新知