题目描述
给出一个整数n(n<)和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个整数(满足条件的个数):
输入输出样例
输入 #1
234 2
2 5
3 6
输出 #1
4
上来二话不说直接爆搜,成功地MLE了4个点,剩下的一个点也成功地WA掉了,震惊之余看了看数据范围,算了一下最多有个不同的数...(不WA,不MLE才怪...)
切换思路,仔细想了一下,因为没有变成0的可能,所以数的位数不会改变,所以所有位上的可能出现的数的个数的乘积就是答案(好绕)
首先遍历边,把所有数可能改变的数的个数记录下来. 然后直接遍历原字符串把每一位可能出现的数的个数乘起来就行了。要用到高精度乘法。。。
ACCODE
#include <iostream>
#include <cstring>
using namespace std;
struct node
{
int to;
int nxt;
}edge[20];
int head[20];
int vis[20];
int k[20]; //记录每种数字可能变成的数字的个数
int cnt=0;
int ans[101];
int len=0;
void addedge(int from,int to)
{
edge[cnt]={to,head[from]};
head[from]=cnt++;
}
void dfs(int p)
{
for(int i=head[p];i!=-1;i=edge[i].nxt)
{
int v=edge[i].to;
if(vis[v]) continue;
vis[v]=1;
dfs(v);
}
}
void mul(int t)
{
int j=0;
for(int i=0;i<=len;i++)
{
ans[i]*=t;
ans[i]+=j;
j=ans[i]/10;
ans[i]%=10;
}
while(j)
{
ans[++len]=j;
j/=10;
ans[len]%=10;
}
} //高精乘(写的好丑。。。)
void getk()
{
for(int i=0;i<10;i++)
{
memset(vis,0,sizeof(vis));
vis[i]=1;
dfs(i);
for(int j=0;j<10;j++)
if(vis[j])
k[i]++;
}
}
void getans(string a)
{
ans[0]=1;
for(int i=0;i<a.size();i++)
{
int t=a[i]-'0';
mul(k[t]);
}
for(int i=len;i>=0;i--)
cout<<ans[i];
}
int main()
{
memset(head,-1,sizeof(head));
int n;
string a;
cin>>a>>n;
for(int i=0;i<n;i++)
{
int c,d;
cin>>c>>d;
addedge(c,d);
}
getk();
getans(a);
return 0;
}