2021/01/24弗洛伊德算法&高精度

在这里插入图片描述
首先通过初步阅读题目,就可以发现这是一个关于排列组合的问题,但仔细研读以及通过阅读题解后发现,这里存在一个隐含的条件,例如1->2,2->3,那么1也可以通过两次变化变成3,这里就可以初步发现这个问题实际已经转化成了一个图论的问题,翻译一下就是有若干个城市,现在已知若干条道路可以将其中的一些城市连接起来,问你其中全部可以互相到达的城市,这里就可以用到弗洛伊德算法。`

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]);
}

这大概就是一个最最基础的弗洛伊德算法的模型,简单解释一下就是看看i,j之间是否通过k之间可以联系起来。我个人觉得这里最需要注意的一点是中间值k要放在最开始进行遍历。

然后这里还要用到高精度的一些东西,因为这里的数据范围已经远远超过了long long 所以必须要用到高精度的东西。

 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'];//这里f数组代表的每个数的通航数量
    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];  //输出

总结起来就是一句话,先是用弗洛伊德算法算出每个数与之相连(包括它本身)数的个数,然后实际上就是遍历你输入的这段数,把他们对应相连数的个数全部乘起来即可,就算没有数与之相连,那么就是1,不影响最终的结果。最后贴上完整代码

#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;  //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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值