题目链接
https://www.dotcpp.com/oj/problem1492.html
题目大意
每个数(0 ~ 9)可以变换成其他的数(除本身外0 ~ 9)。
给定一个数,问这个数可以有多少种形式(包含原形)
解题思路
思路很简单,把这个数中每一位数可以变换的种数相乘,得到答案。
难点1:如何统计每个数可以变换的种数(含自己)?
难点2:最终答案的最大可能为:每一位数都有10种变换(含自己),答案是10^30,比longlong大,怎么表达这个数?
难点2解决:这么大的数,自然相当高精度乘法(高精度*低精度),解决!
难点1解决:给出的变换规则,相当于一个图,关系是有向边,a能变成b,意味着a到b存在一条有向边。存下所有边之后,我们可以dfs遍历并统计其能到达的所有点的个数,用数组记录下来。进行高精度乘法的时候使用。
高精度*低精度板子
如果不会高精度乘法,建议先看看通过数组实现高精度的板子,再看容器实现的板子
//函数部分
vector<int> mul(vector<int> a,int b){
vector<int> c;
int t=0;
for(int i=0;i<a.size();i++){
t=a[i]*b+t;
c.push_back(t%10);
t/=10;
}
while(t){//把剩余没保存在vector中的数,保存进去
c.push_back(t%10);
t/=10;
}
return c;
}
//主函数部分
vector<int> res;
res.push_back(1);
for(int i=1;i<=len;i++){
res=mul(res,k);//表示k与res相乘
}大佬代码
#include<bits/stdc++.h>
using namespace std;
int len,cnt,k,p,q;
int vis[10],num[10],a[50];
vector<int> v[10];
vector<int> res;
char s[50];
void dfs(int x){
for(int i=0;i<v[x].size();i++){
int next=v[x][i];
if(vis[next]) continue;
cnt++;
vis[next]=1;
dfs(next);
}
return ;
}
vector<int> mul(vector<int> a,int b){
vector<int> c;
int t=0;
for(int i=0;i<a.size();i++){
t=t+a[i]*b;
c.push_back(t%10);
t/=10;
}
while(t){
c.push_back(t%10);
t/=10;
}
return c;
}
int main(){
cin>>s+1>>k;
//存边
for(int i=1;i<=k;i++){
cin>>p>>q;
v[p].push_back(q);
}
//逆置字符串
len=strlen(s+1);
for(int i=1;i<=len;i++)
a[len-i+1]=s[i]-'0';
//dfs
for(int i=0;i<=9;i++){
cnt=1;//初始化的时候直接加上自己这个点
memset(vis,0,sizeof vis);
vis[i]=1;//勿忘,但其实好像对本题的数据没影响
dfs(i);
num[i]=cnt;//num用于存数字i可变种数
}
//*
res.push_back(1);//勿忘
for(int i=1;i<=len;i++){
res=mul(res,num[a[i]]);
}
//输出
for(int i=res.size()-1;i>=0;i--)
cout<<res[i];
cout<<endl;
return 0;
}我的代码
和大佬的差别在于dfs。我的比较混乱,多用了个set容器。其他部分一样。
所以,可以忽略我的代码
#include<bits/stdc++.h>
using namespace std;
const int N=50;
int fa;
int vis[10];
vector<int> a[10];
int cnt[N];
set<int> num[10];
char n[N];
int c[N];
vector<int> mul(vector<int> a,int b){
vector<int> c;
int t=0;
for(int i=0;i<a.size();i++){
t=a[i]*b+t;
c.push_back(t%10);
t/=10;
}
while(t){
c.push_back(t%10);
t/=10;
}
return c;
}
void dfs(int x){
for(int i=0;i<a[x].size();i++){
int tmp=a[x][i];
if(tmp==fa || vis[tmp]) continue;
num[fa].insert(tmp);
vis[tmp]=1;
dfs(tmp);
}
return ;
}
int main(){
int k,p,q;
cin>>n+1>>k;
//存边
for(int i=1;i<=k;i++){
cin>>p>>q;
a[p].push_back(q);
}
//找到每个数能变成的全部数
for(int i=0;i<=9;i++){
fa=i;
memset(vis,0,sizeof vis);
vis[i]=1;
dfs(i);
}
//计算每个数能变成其他数的个数
for(int i=0;i<=9;i++)
cnt[i]=num[i].size();
//逆置字符串
int len=strlen(n+1);
for(int i=1;i<=len;i++)
c[len-i+1]=n[i]-'0';
//高精度乘法
vector<int> res;
res.push_back(1);
for(int i=1;i<=len;i++){
res=mul(res,cnt[c[i]]+1);
}
//输出
for(int i=res.size()-1;i>=0;i--)
cout<<res[i];
cout<<endl;
return 0;
} 总结
这是我们昨天蓝桥训练的一道题,昨天还不会,今天看完高精度,思路都清晰了,直接AC,神了!

京公网安备 11010502036488号