SSL 1021、洛谷 1037——产生数(dfs或高精度+Floyd)

题目描述

给出一个整数 n(n<10^30) 和 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:
234 2
2 5
3 6
输出样例#1:
4


这题我只实现了高精度+Floyd的做法。
现将每两个可以互相转换的数用数组存起来如:dis[x][y]=true
在进行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 ()
{
   cin >> str >> k;
  while (k--) 
  {
    int a,b;
    cin >> a >> b;
    vis[a][b] = true; 
  }
  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]++;  
  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;
}
原文地址:https://www.cnblogs.com/Comfortable/p/8412370.html