链接:https://ac.nowcoder.com/acm/contest/1077/C
来源:牛客网
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 131072K,其他语言262144K
64bit IO Format: %lld题目描述
给出一个整数 n(n<1030) 和 k 个变换规则(k<=15)。
规则:
一位数可变换成另一个一位数:规则的右部不能为零。
例如:n=234。有规则(k=2):
2-> 5
3-> 6
上面的整数 234 经过变换后可能产生出的整数为(包括原数):
234
534
264
564
共 4 种不同的产生数
问题:
给出一个整数 n 和 k 个规则。
求出:
经过任意次的变换(0次或多次),能产生出多少个不同整数。仅要求输出个数。输入描述:
输入格式为: n kx1 y1
x2 y2
... ...
xn yn
输出描述:
一个整数(满足条件的个数)示例1
输入
复制
234 2 2 5 3 6输出
复制
4
注意:一开始立即错题意,实际题意是2能变成4,4能变成5,那么2就能变成4和 5;这就很容易想到Floyd算法,求出每个数能变成的其他数的个数;
但是最大的结果是小于9^30
#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<vector>
#include<cmath>
#include<string>
#include<map>
#include<queue>
using namespace std;
typedef long long ll;
ll p[50];
int main(){
ll flag[10][10];
memset(flag,0,sizeof(flag));
string s;ll k;
cin>>s>>k;
for(ll i=0;i<k;i++){
ll x,y;
cin>>x>>y;
flag[x][y]=1;//x能变成y
}
//Floyd算法
for(ll k=0;k<=9;k++){
for(ll j=1;j<=9;j++){
for(ll i=0;i<=9;i++){
if(flag[i][k]&&flag[k][j]){
flag[i][j]=1;
}
}
}
}
ll dp[10];
memset(dp,0,sizeof(dp));
for(ll i=0;i<=9;i++){
flag[i][i]=1;//原数也算一种
for(ll j=0;j<=9;j++){
dp[i]+=flag[i][j];
}
}
ll sum=1,z;
p[0]=1;
ll len=s.size();
//接下来,使用乘法原理
for(ll i=0;i<len;i++){
z=0;
for(ll j=0;j<=50;j++){
p[j]=(p[j]*dp[s[i]-'0']+z);
z=p[j]/10;//z是进位
p[j]%=10;//算出该步运算第j位的数
}
}
ll mm=50;
while(mm){
if(p[mm]!=0){
break;
}
mm--;
}
//最终的大数一位一位的输出
for(ll i=mm;i>=0;i--){
cout<<p[i];
}
cout<<endl;
return 0;
}