产生数
产生数
题目描述
给出一个整数n(n<10^30)和k个变换规则(k<=15)。
规则:
- 1个数字可以变换成另一个数字;
- 规则的右部不能为零。
例如: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能够间接转化成的数的数量
然后根据乘法原理扫一遍原数字,*起来就可以了
如何得到每一个数N能够间接转化成的数z的数量
这里介绍图论的观点
设有向图G , 若i点能够间接到达j点 ,那么根据题意, 数字i就能转化为j
floyd-warshall !
这个算法不用介绍了吧,不懂的话就百度,基本原理就是i点能到k点,k点能到j点,那么i就能到j (对于这道题而言
(一定不要忘记是k,i,j的顺序
话不多说上代码
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 10;
string n;
int k, g[10][10];
int d[10];
void floyd() {
for (int k = 0;k <= 9;++k) {
for (int i = 0;i <= 9;++i) {
for (int j = 0;j <= 9;++j) {
g[i][j] |= g[i][k] && g[k][j];
}
}
}
}
struct high {
int a[maxn], len;
void init() {
len = 1;
a[0] = 1;
}
void mul(int x) {
for (int i = 0;i < len;++i) {
a[i] *= x;
}
for (int i = 0;i < len;++i) {
a[i + 1] += a[i] / 10;
a[i] %= 10;
}
while (a[len]) {
a[len + 1] += a[len] / 10;
a[len] %= 10;
++len;
}
}
void print() {
for (int i = len - 1;i >= 0;--i) {
printf("%d", a[i]);
}
}
};
int main() {
cin >> n >> k;
for (int i = 1;i <= k;++i) {
int u, v; scanf("%d%d", &u, &v);
g[u][v] = 1;
}
for (int i = 0;i <= 9;++i) g[i][i] = 1;
floyd();
for (int i = 0;i <= 9;++i) {
for (int j = 0;j <= 9;++j) {
d[i] += g[i][j];
}
}
high ans;
ans.init();
for (int i = 0;i < n.size();++i) {
int cur = n[i] - '0';
ans.mul(d[cur]);
}
ans.print();
}
第一次写markdown,以后都会是markdown

浙公网安备 33010602011771号