题目描述
给出一个整数 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;
}