首页 > 代码库 > NOIP2002 产生数
NOIP2002 产生数
题目描述
给出一个整数n(n<1030) 和k个变换规则(k<=15)。
规则:
一位数可变换成另一个一位数:
规则的右部不能为零。
例如:n=234。有规则(k=2):
2->5
3->6
上面的整数234经过变换后可能产生出的整数为(包括原数):
234
534
264
564
共4种不同的产生数
问题:
给出一个整数n和k个规则。求出:
经过任意次的变换(0次或多次),能产生出多少个不同整数。仅要求输出个数。
输入格式
每个测试文件只包含一组测试数据,每组输入的第一行输入两个整数n和k(n<1030,k<=15)。
接下来k行每行输入一个规则,每个规则由两个整数构成。
输出
对于每组输入数据,输出一个整数,表示满足条件的个数。
样例输入
234 2
2 5
3 6
样例输出
4
需要考虑两点
1、一共有15种操作 说明一个数可以变成多个不同的数
如果存在 2个操作 a->b b->c 则a既可以变到b也可以变到c
所以可以通过DFS求每个数可变得其他数的个数
2、最多可能有30位数 所以最大可能9^30
需要模拟大数乘法 而每次乘数有一个 不超过10 所以并不难
#include<iostream> #include<cstdio> #include<cstring> using namespace std; int op[10][10]; char str[105]; int vis[10]; int value[32]; int maxlen=1; void dfs(int a) //搜索出每个数可以到达的数的个数 用SS保存 { if(vis[a]) return; vis[a]=1; ss++; for(int i=0;i<=9;i++) { if(op[a][i]==1) dfs(i); } } void multiple(int x) //最大可能 9^30 超long long 所有模拟大数乘法 { int carry=0; //carry表示进位 for(int i=1;i<=maxlen;i++) { value[i]=value[i]*x+carry; carry=value[i]/10; value[i]=value[i]%10; } if(carry>0) value[++maxlen]=carry; return; } int main() { int m,n,i,j,k; int s; value[1]=1; memset(op,0,sizeof(op)); scanf("%s%d",str,&k); int a,b; if(k==0) { cout<<1<<endl; return 0; } while(k--) { scanf("%d%d",&a,&b); op[a][b]=1; //op[a][b]代表a可以到b } int len=strlen(str); for(i=0;i<len;i++) { memset(vis,0,sizeof(vis)); ss=0; dfs(str[i]-'0'); //求出每位可转换数的乘积 //其实可以用一个数组保存每个数可转换的数的个数 multiple(ss); } for(i=maxlen;i>=1;i--) cout<<value[i]; cout<<endl; return 0; }
NOIP2002 产生数
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。