产生数
题目
给出一个整数 n 和 k 个变换规则。
规则:
一位数可变换成另一个一位数:
规则的右部不能为零。
例如:n=234。有规则 k=2 :
2-> 5
3-> 6
上面的整数 234 经过变换后可能产生出的整数为(包括原数):
234
534
264
564
共 4 种不同的产生数
输入
给出一个整数 n 和 k 个规则。
输出
经过任意次的变换(0次或多次),能产生出多少个不同整数。
仅要求输出个数。
输入样例
234 2
2 5
3 6
输出样例
4
数据范围
n<10^30
k<=15
思路
这道题我们可以用Floyed算法求出由这个数可以转变到哪几个数(包括自身),再把整数n到每一位所可以转变的数的个数乘在一起,就是答案了。
有一点要注意的就是,因为这个答案会很大,所以乘起来的时候要用高精乘。
代码
#include<cstdio>
#include<cstring>
using namespace std;
int m,w,x,y,ans[500001],f[10];
char n[31],cc;
bool a[10][10];
int main()
{
cc=getchar();//读入
while (cc<='9'&&cc>='0')//读入
{
n[w++]=cc;
cc=getchar();
}
w--;//求出整数n到位数
scanf("%d",&m);//读入
for (int i=1;i<=m;i++)
{
scanf("%d%d",&x,&y);//读入
a[x][y]=1;//标记
}
for (int k=0;k<=9;k++)
{
a[k][k]=1;//自身可以转变到自身
for (int i=0;i<=9;i++)
for (int j=0;j<=9;j++)
a[i][j]=a[i][j]||(a[i][k]&&a[k][j]);//Floyed算法
}
for (int i=0;i<=9;i++)
{
for (int j=0;j<=9;j++)
if (a[i][j]) f[i]++;//求出每个数所可以转变的数的个数
}
ans[0]=1;//初始化
for (int i=0;i<=w;i++)//高精乘
{
int jw=0,xx=f[n[i]-48];
for (int i=0;i<=500;i++)
{
ans[i]=ans[i]*xx+jw;
jw=ans[i]/10;
ans[i]%=10;
}
}
int lenc=500;
while (ans[lenc]==0) lenc--;//求出答案的位数
for (int i=lenc;i>=0;i--) printf("%d",ans[i]);//输出
return 0;
}