华师一附中OI组

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 1325|回复: 1
打印 上一主题 下一主题

P1092 虫食算

[复制链接]

738

主题

1485

帖子

5420

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
5420
跳转到指定楼层
楼主
发表于 2018-5-26 20:29:37 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
https://www.luogu.org/problemnew/show/P1092

题目描述
所谓虫食算,就是原先的算式中有一部分被虫子啃掉了,需要我们根据剩下的数字来判定被啃掉的字母。来看一个简单的例子:

43#9865#045
+  8468#6633
44445509678
其中 $#$ 号代表被虫子啃掉的数字。根据算式,我们很容易判断:第一行的两个数字分别是 55 和 33 ,第二行的数字是 55 。

现在,我们对问题做两个限制:

首先,我们只考虑加法的虫食算。这里的加法是 NN 进制加法,算式中三个数都有 NN 位,允许有前导的 00 。

其次,虫子把所有的数都啃光了,我们只知道哪些数字是相同的,我们将相同的数字用相同的字母表示,不同的数字用不同的字母表示。如果这个算式是 NN 进制的,我们就取英文字母表午的前 NN 个大写字母来表示这个算式中的 00 到 N-1N−1 这 NN 个不同的数字:但是这 NN 个字母并不一定顺序地代表 00 到 N-1N−1 。输入数据保证 NN 个字母分别至少出现一次。

BADC
+CBDA
DCCC
上面的算式是一个4进制的算式。很显然,我们只要让 ABCDABCD 分别代表 01230123 ,便可以让这个式子成立了。你的任务是,对于给定的 NN 进制加法算式,求出 NN 个不同的字母分别代表的数字,使得该加法算式成立。输入数据保证有且仅有一组解。

输入输出格式
输入格式:
包含四行。
第一行有一个正整数 N(N \le 26)N(N≤26) 。

后面的三行,每行有一个由大写字母组成的字符串,分别代表两个加数以及和。这3个字符串左右两端都没有空格,从高位到低位,并且恰好有 NN 位。

输出格式:
一行,即唯一的那组解。

解是这样表示的:输出 NN 个数字,分别表示 A,B,C,…A,B,C,… 所代表的数字,相邻的两个数字用一个空格隔开,不能有多余的空格。

输入输出样例
输入样例#1:
5
ABCED
BDACE
EBBAA
输出样例#1:
1 0 3 4 2
说明
对于30%的数据,保证有 N \le 10N≤10 ;

对于50%的数据,保证有 N \le 15N≤15 ;

对于全部的数据,保证有 N \le 26N≤26 。

noip2004提高组第4题
回复

使用道具 举报

14

主题

106

帖子

317

积分

中级会员

Rank: 3Rank: 3

积分
317
沙发
发表于 2018-10-25 21:25:26 | 只看该作者
  1. #include<iostream>
  2. #include<algorithm>
  3. #include<cstdio>
  4. #include<string>
  5. using namespace std;
  6. #define FOR(i,n,m) for(int i=n;i<=m;i++)
  7. #define For(i,n,m) for(int i=n;i>=m;i--)
  8. string s1,s2,s3;
  9. int n,word[30],t,a[30],b[30],c[30],num[30];
  10. bool bb[30];
  11. void doit(int x)
  12. {
  13.     if(!bb[x])
  14.     {
  15.         word[t++]=x;
  16.         bb[x]=1;
  17.     }
  18. }
  19. bool judge(){
  20.     for(int i=n-1,x=0;i>=0;i--){
  21.         int A=num[a[i]],B=num[b[i]],C=num[c[i]];
  22.         if((A+B+x)%n!=C) return 0;
  23.         x=(A+B+x)/n;
  24.     }
  25.     return 1;
  26. }
  27. bool prune(){
  28.     if(num[a[0]]+num[b[0]]>=n) return 1;
  29.     for(int i=n-1;i>=0;i--){
  30.         int A=num[a[i]],B=num[b[i]],C=num[c[i]];
  31.         if(A==-1||B==-1||C==-1) continue;
  32.         if((A+B)%n!=C&&(A+B+1)%n!=C) return 1;
  33.     }return 0;
  34. }
  35. void dfs(int x)
  36. {
  37.     if(prune()) return;
  38.     if(x==n){
  39.         if(judge()) {
  40.                 FOR(i,0,n-1) cout<<num[i]<<" ";
  41.                 exit(0);
  42.         }
  43.         return;
  44.     }
  45.     for(int i=n-1;i>=0;i--)
  46.         if(!bb[i]){
  47.             num[word[x]]=i;
  48.             bb[i]=1;
  49.             dfs(x+1);
  50.             num[word[x]]=-1;
  51.             bb[i]=0;
  52.         }
  53.     return;
  54. }
  55. int main()
  56. {
  57.     cin>>n;cin>>s1>>s2>>s3;
  58.     FOR(i,0,n-1) a[i]=s1[i]-'A',b[i]=s2[i]-'A',c[i]=s3[i]-'A';
  59.     For(i,n-1,0) doit(a[i]),doit(b[i]),doit(c[i]);
  60.     FOR(i,0,27) bb[i]=0;FOR(i,0,27) num[i]=-1;
  61.     dfs(0);
  62.     return 0;
  63. }
复制代码
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|小黑屋|服务支持:DZ动力|华师一附中OI组  

GMT+8, 2024-11-2 02:18 , Processed in 0.138089 second(s), 22 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表