题目
题解
DFS + 高精度。
大致说一下题目意思:
给出一组变化方式,允许数字a
变到数字b
,a,b
属于1~9
;
有一个最多三十位的数,问这个数最多可以变成多少个数(含自己)。
怪不得正确率这么低,都是因为忘记开高精度了!
先不考虑高精度,我们来实现一下:
每一位都是独立的,因此我们求出每一位的数最多有多少种变化方式,之后每一位的变化方式数相乘就是最终答案,这样算正好结果也包含原数的情况。
这里求每一位的变化方式数用到dfs,只要遍历过就不再遍历了,dfs部分代码如下:
void dfs(int x) {
for(int i = 0;i < v[x].size();i ++) {
if(vis[v[x][i]]) continue;
vis[v[x][i]] = 1;
res++;
dfs(v[x][i]);
}
}
我用vector
存的,v[i][j]
表示数字i
能变化到的第j
个数是多少;
res是用于统计当前位,总共有多少变化方式,即变化方式数;
再就是注意遍历每一位的时候都要提前memset 0
一下vis
。
求完每一位的次数之后相乘就可以得到正确答案了。
但是最多有三十位啊,也就是最多可能是30
个9
相乘,大概是4e28
,long long
最大也就19
位,只能高精度了。
高精度实现:
这里的高精度无非就涉及两种,一种是dfs代码部分的res++
,需要使用“高精度 + 1”的模板;另一种是在求出每一位的变化方法数求乘积时用到的“高精度 * 高精度”。
如果只是模板忘记了的小伙伴可以直接看这几个图,要是直接不会的小伙伴可以戳这里
高精度 * 高精度:
高精度加法(这里给的“高精度 + 高精度”,不过“高精度 + 低精度”也差不多,原理类似):
这次实现的时候我没用直接用数组去存,因为传数组还是件麻烦事(其实是我菜,忘记传数组的规则了,怕出错又懒得搜),所以我是用结构体封装了一下数组和数组存的有效数字的位数。
注意m
也要以字符串的形式输入。
代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
struct Bignumber {
int num[35];
int cnt;
Bignumber() {memset(num, 0, sizeof num);cnt = 0;}
Bignumber(int) {memset(num, 0, sizeof num); num[1] = 1; cnt = 1;}
};
Bignumber ans = Bignumber(1), res;
int k, vis[10], a, b;
vector<int> v[10];
string m;
Bignumber ADD(Bignumber big, int d) { // 高精度 + 1
big.num[1] += d;
big.num[2] += big.num[1]/10;
big.num[1] %= 10;
for(int i = 2;i <= big.cnt;i ++) {
big.num[i+1] += big.num[i]/10;
big.num[i] %= 10;
}
if(big.num[big.cnt+1]) big.cnt++;
return big;
}
Bignumber MUL(Bignumber a, Bignumber b) { // 高精度 * 高精度
Bignumber res;
int n = a.cnt, m = b.cnt;
for(int i = 1;i <= n;i ++)
for(int j = 1;j <= m;j ++) {
res.num[i+j-1] += a.num[i] * b.num[j];
res.num[i+j] += res.num[i+j-1]/10;
res.num[i+j-1] %= 10;
}
if(res.num[n+m]) res.cnt = n+m;
else res.cnt = n+m-1;
return res;
}
void dfs(int x) {
for(int i = 0;i < v[x].size();i ++) {
if(vis[v[x][i]]) continue;
vis[v[x][i]] = 1;
res = ADD(res, 1);
dfs(v[x][i]);
}
}
int main()
{
cin>>m>>k;
for(int i = 1;i <= k;i ++) cin>>a>>b, v[a].push_back(b);
for(int i = 0;i < m.size();i ++) {
memset(vis, 0, sizeof vis);
res = Bignumber(1);
vis[m[i]-'0'] = 1;
dfs(m[i]-'0');
ans = MUL(ans, res);
}
for(int i = ans.cnt;i >= 1;i --) cout<<ans.num[i];
return 0;
}