产生数 洛谷p1037

来源:互联网 发布:bt种子下载器for mac 编辑:程序博客网 时间:2024/06/03 22:56

题目描述

给出一个整数 n(n<10^30) 和 k 个变换规则(k<=15)。

规则:

一位数可变换成另一个一位数:

规则的右部不能为零。

例如:n=234。有规则(k=2):

2->5

3->6

上面的整数 234 经过变换后可能产生出的整数为(包括原数):

234 534 264 564 共 4 种不同的产生数

问题:

给出一个整数 n 和 k 个规则。

求出:

经过任意次的变换(0次或多次),能产生出多少个不同整数。

仅要求输出个数。

输入输出格式

输入格式:

键盘输人,格式为:

n k x1 y1 x2 y2 ... ...

xn yn

输出格式:

屏幕输出,格式为:

一个整数(满足条件的个数):

输入输出样例

输入样例#1:

234 2

2 5

3 6

输出样例#1:

4

 

设F[i]表示从数字i出发可以变换成的数字个数(这里的变换可以是直接变换,也可以是间接变换,比如样例中的1可以变换成2,而2又可以变换成3,所以1也可以变换成3;另外自己本身不变换也是一种情况)。那么对于一个长度为m位的整数a,根据乘法原理,能产生的不同的整数的个数为:F[a[1]]*F[a[2]]*F[a[3]]*…*F[a[m]]。

floyd+高精度秒杀.

#include<iostream>#include<cstdio>#include<cstring>#include<string>using namespace std;struct bign{int l,w[100005];bign(){l=1;memset(w,0,sizeof(w));}bign(int x){l=0;memset(w,0,sizeof(w));while(x){w[l]=x%10;x/=10;++l;}}bool operator <(bign& x){int i;if(l<x.l) return 1;if(l>x.l) return 0;for(i=l-1;i>=0;i--){if(w[i]>x.w[i]) return 0;if(w[i]<x.w[i]) return 1;}return 0;}bign operator *(bign& x){int i,j,tmp;bign ans;ans.l=l+x.l;for(i=0;i<l;i++){for(j=0;j<x.l;j++){tmp=ans.w[i+j]+w[i]*x.w[j];ans.w[i+j+1]=tmp/10;ans.w[i+j]=tmp%10;}}while(ans.l&&!ans.w[ans.l-1]) ans.l--;return ans;}void write(){int i;if(!l) puts("0");else{for(i=l-1;i>=0;i--){printf("%d",w[i]);}printf("\n");}}};int d[10][10],f[10];bign ff[10];void floyd(){int i,j,k;for(i=0;i<=9;i++){for(j=0;j<=9;j++){for(k=0;k<=9;k++){d[j][k]=d[j][k]|(d[j][i]&d[i][k]);}}}}int main(){string a;int k,i,j,u,v;bign ans;ans=1;//ans.write();cin>>a;scanf("%d",&k);for(i=1;i<=k;i++){scanf("%d%d",&u,&v);d[u][v]=1;}for(i=0;i<=9;i++) d[i][i]=1;floyd();for(i=0;i<=9;i++){for(j=0;j<=9;j++){if(d[i][j]){f[i]++;}}ff[i]=f[i];}for(i=0;i<a.length();i++){ans=ans*ff[(int)(a[i]-'0')];}ans.write();return 0;}

原创粉丝点击