1138 代码等式[附加题]

该题有题解

时间限制:500MS  内存限制:65536K
提交次数:59 通过次数:21

题型: 编程题   语言: G++;GCC

Description

一个代码等式就是形如x1x2...xi=y1y2...yj,这里xi和yj是二进制的数字(0或1)或者是一个变量(如英语中的小写字母)。
每一个变量都是一个有固定长度的二进制代码。例如:
a,b,c,d,e是变且它们的长度分别是4,2,4,4,2。考虑等式:1bad1=acbe,这个等式共有16组解。现要求任给一个等式,计算一共有多少组解。
(变量最多26个,长度和不超过10000)

输入格式

第一行数N为变量个数;
第二行N个数,为每个变量的位数
第三行为一个等式

输出格式

输出解的个数,无解输出0

输入样例

5
4 2 4 4 2
1bad1=acbe

输出样例

16

题解:

可知每个字母变量分为相应长度的01变量,假设这种单位长度的01变量为单位变量。

总思路:将值必须是一样的单位变量放进同一个集合。(在等式的牵连下,某些单位变量的值要对应变化)

具体做法:

1.为每个单位变量分配一个空间(从2开始),存放其所属集合(由于等式中有0和1作为常量,所以也要为0和1分配空间,看其所属集合)。

2.首先是判断等式两边长度是否相等,若相等,则继续。

3.通过并查集,逐步为每个单位变量找到所属的集合,(期间如果发现常量1和常量0被要求在同一个集合,则不可能实现,直接退出)

4.遍历每一个单位变量(从0开始),统计集合数sum,则 ans = pow(2,sum-2) 减去2是因为常量0和常量1所在的集合的值已经确定了。

注意:代码等式可能只出现01的其中一个或不出现,那又减去2是否合法呢?不是应该出现几种常量才减去几吗? 其实在遍历单位变量找集合时,从0开始,已经假设两个变量都出现了,再减去它,不管有没有真的出现,都不影响答案。类似的好像叫做虚拟变量。

学习之处:将变量放到格子当中,通过下标与变量形成映射。

代码如下:

 #include<cstdio>//scau 1138 代码等式
#include<cstring>
#include<cstdlib>
#include<cmath> int fa[],length[],beg[]; int find(int x)
{
return (x==fa[x]?x:find(fa[x]));
} void Union(int m, int n)//这里可以优化,将深度大的合并到深度低的,这样查找速度会加快。用迭代。
{
m = find(m);
n = find(n);
if(m!=n)
fa[m] = n;
} int main()
{
int n, s1[],s2[],len1 = ,len2 = ;
scanf("%d",&n);
scanf("%d",&length[]);
beg[] = ;
for(int i = ; i<n; i++)//为每个字母变量分配相应长度的单位变量,与此同时,每个单位变量都与数组的下标形成了一一对应的关系
{
scanf("%d",&length[i]);
beg[i] = beg[i-] + length[i-];
} char ch;
getchar();
while((ch= getchar())!='=')//处理等式,将其转换成以单位变量为形式的串,并将串存到数组中,等待并查集
{
if(ch=='' || ch=='')
s1[len1++] = ch-''; else
{
for(int i = ; i<length[ch-'a']; i++)
s1[len1++] = beg[ch-'a'] + i;
}
} while((ch= getchar())!='\n')
{
if(ch=='' || ch=='')
s2[len2++] = ch-''; else
{
for(int i = ; i<length[ch-'a']; i++)
s2[len2++] = beg[ch-'a'] + i;
}
} if(len1!=len2)
{
printf("0\n");
return ;
} for(int i = ; i<beg[n-]+length[n-]; i++) //初始化每个单位变量的集合为自己
fa[i] = i; for(int i = ; i<len1; i++)//并查集
{
if(s1[i]+s2[i]==)
{
printf("0\n");
return ;
} Union(s1[i],s2[i]);
} int ans = ;
for(int i = ; i<beg[n-]+length[n-]; i++)//遍历每个单位变量,统计集合个数
if(fa[i]==i) ans++; printf("%.0lf\n",pow(,ans-));
return ;
}

最新文章

  1. Azure SQL Database (20) 使用SQL Server 2016 Upgrade Advisor
  2. 异步编程系列第05章 Await究竟做了什么?
  3. 【Excel】宏之初认识
  4. Bmob基础
  5. java中wait/notify机制
  6. scala中的trait
  7. repeater做删除前弹窗询问
  8. LINQ to SQL使用教程
  9. Codeforces Round #180 (Div. 2) A. Snow Footprints 贪心
  10. 利用python 获取 windows 组策略
  11. GNU_makefile_template
  12. thinkphp的目录结构
  13. Android 调用webService(.net平台)
  14. yzoi2223集合构造的详细解法
  15. 如何给对话框中的控件发送消息呢?Windows消息分类
  16. SQLite高级:一库建多表,封装类
  17. 关于vue-clidown到本地后,拷贝文件库到另外一台电脑上npm run dev编译报错的处理
  18. C#简单接口和继承示例详解——快速入门
  19. nvm 安装使用
  20. Container&amp;injection

热门文章

  1. Netty学习_Netty框架入门教程:Netty入门之HelloWorld实现
  2. javascript 函数初探 (六)--- 闭包初探#2
  3. Class definition
  4. sshpass结合ssh和scp可以自动完成密码登录,无需手动输入密码
  5. Linux退出时出现there are stopped jobs如何解决?
  6. ArcGIS 10.1系列产品 升级安装至 ArcGIS 10.2
  7. ActiveMQ测试工具
  8. 获取Android屏幕尺寸、控件尺寸、状态栏/通知栏高度、导航栏高度
  9. HTML5开发移动web应用—JQuery Mobile(1)
  10. (转)Understanding C parsers generated by GNU Bison