[noip2002] 产生数
题目描述
给出一个整数 n (n<1030)和 k 个变换规则 (k < 15) 。
规则:
一位数可变换成另一个一位数:
规则的右部不能为零。
例如:n = 234 。有规则( k=2 ):
2-> 5
3-> 6
上面的整数 234 经过变换后可能产生出的整数为(包括原数):
234 534 264 564
共44 种不同的产生数
问题:
给出一个整数 n 和 k 个规则。
求出:
经过任意次的变换( 0 次或多次),能产生出多少个不同整数。
仅要求输出个数。
思路
floyd+高精度,用floyd求出每个数字可以变成多少种数字,根据乘法原理乘起来]
#include#include <string> using namespace std; string str; int k,vis[10][10],f[10],num[101]; inline void floyd() { //弗洛伊德 for (int k = 0;k <= 9;k++) for (int i = 0;i <= 9;i++) for (int j = 0;j <= 9;j++) vis[i][j] = vis[i][j] || (vis[i][k] && vis[k][j]); } int main (){ ios::sync_with_stdio(false); cin >> str >> k; while (k--) { int a,b; cin >> a >> b; vis[a][b] = true; //a可以变成b } for (int i = 0;i <= 9;i++) vis[i][i] = true; //自己可以变成自己 floyd(); for (int i = 0;i <= 9;i++) for (int j = 0;j <= 9;j++) if (vis[i][j]) f[i]++; //求出i可以变成多少种数字 int len = 2; num[1] = 1; for (int i = 0;i < (int)str.length();i++) { //高精度 for (int j = 1;j <= 100;j++) num[j] *= f[str[i]-'0']; for (int j = 1;j <= 100;j++) if (num[j] >= 10) { //进位 num[j+1] += num[j]/10; num[j] %= 10; } while (num[len]) len++; //求出长度 } for (int i = len-1;i >= 1;i--) cout << num[i]; //输出 return 0; }