[noip2002] 产生数 - Floyd+高精

题目描述

给出一个整数 $n(n<10^{30})$ 和 $k$ 个变换规则 $(k \le 15)$ 

规则:

一位数可变换成另一个一位数:

规则的右部不能为零。

例如: $n$ $ = $ $234$ 。有规则( $k=2$ ):

$2$-> $5$
$3$-> $6$
上面的整数 $234$ 经过变换后可能产生出的整数为(包括原数):

$234$
$534$
$264$
$564$
44 种不同的产生数

问题:

给出一个整数 $n$ 和 $k$ 个规则。

求出:

经过任意次的变换( $0$ 次或多次),能产生出多少个不同整数。

仅要求输出个数。

思路

floyd+高精度,用floyd求出每个数字可以变成多少种数字,根据乘法原理乘起来

#include <iostream>
#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;
}

猜你喜欢

转载自www.cnblogs.com/xzj213/p/10586089.html