一.题目概括
一个整数 n 和 k 个数位变化规则。求出经过任意次的变换(0 次或多次),能产生出多少个不同整数。(变化规则示例:2 4表示数字“2”可以变化为数字“4”)
输出方案数(注意数字本身保持不变也算一种方案)
二.关键点
1.纯暴力(STLset)
设结构体数组f(或使用pair)存储,深搜一遍,将变化字符串存入集合st中,最后输出st中字符串数字(由于集合可以自动去重,所以可以统计不重合方案数)
这种方法不无优点,比如简单易懂易上手(本人一开始也是使用这种方法),如果数据范围适合,也不是不可以使用
但是看数据限制:n<=10^30,所以只能得到60分
2.高精度+乘法原理
(1).乘法原理
如果实现一个目标必须经过n个步骤,第k步又可以有种不同方式来实现,那么实现这个目标总共有种方法。
--引自百度
简单来说,以样例
234 2
2 5
3 6
为例:字符串s(即“234”)的变化方案为
“2”的变化方案数*“3”的变化方案数*“4”的变化方案数
得到表格
2 | 1+1=2(不变+2变5) |
3 | 1+1=2(不变+3变6) |
4 | 1=1(不变) |
234(答案) | 2*2*1=4(变化2*变化3*变化4) |
但是随之得来一个问题:
如果溢出,怎么办?
(2) 高精度
已知int类的最大值为2147483647,long long类的最大值为9223372036854775807,unsigned long long类的最大值为18446744073709551615,_int128类的最大值为2^(128-1)-1
但是我们知道乘法的增长是恐怖的,按照规定的数据范围,无法保证是否可以用以上常用的数据存储范围来存储答案
所以可以引入高精度算法(理论上,如果内存足够大,高精度的表示上限可以达到正无穷)
高精度的精髓就是用数组来表示数,数组第i位表示数字第i位(但是为了方便计算,通常将数组表示反转),这里只介绍高精*低精的代码
第一步:将数组每一位乘以低精度数字x
第二步:遍历数组,处理进位
第三步:处理数组长度
第四步:逆序输出
以下代码建议熟练背诵
//高精乘低精板子
void HPNmul(int x[],int y){//x表示高精度数组,y表示低精度数
for(int i=1;i<=x[0];i++)x[i]*=y;
for(int i=1;i<=x[0];i++){
if(x[i]>=10){
x[i+1]+=x[i]/10;
x[i]%=10;
if(i==x[0])x[0]++;
}
}
}
三.代码
1.暴力代码(60分)
//也求助一下 能不能继续优化到100
#include <iostream>
#include <string>
#include <set>
using namespace std;
struct Node{
char x,y;
Node(){}
Node(char a,char b):x(a),y(b){}
}f[20];
string s;
int n,ct=1;
char u,v;
set<string> st;
void dfs(string s){
for(int i=1;i<=n;i++){
int pos=s.find(f[i].x);
if(pos!=string::npos){
string s1=s;
s1[pos]=f[i].y;
if(!st.count(s1)){
st.insert(s1);
ct++;
dfs(s1);
}
}
}
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin>>s>>n;
for(int i=1;i<=n;i++){
cin>>u>>v;
f[i]=Node(u,v);
}
st.insert(s);
dfs(s);
cout<<ct;
}
时间:
2.AC代码(高精度+乘法原理)
#include <iostream>
#include <cstring>
#define C vis[c]
using namespace std;
struct Node{
char x,y;
Node(){}
Node(char a,char b):x(a),y(b){}
}f[20];
string s;
int n,u,v,ct[105],tct;
bool vis['9'+5];
void dfs(char c){
if(C)return;
tct++;
C=true;
for(int i=1;i<=n;i++){
if(f[i].x==c)dfs(f[i].y);
}
}
void HPNmul(int x[],int y){
for(int i=1;i<=x[0];i++)x[i]*=y;
for(int i=1;i<=x[0];i++){
if(x[i]>=10){
x[i+1]+=x[i]/10;
x[i]%=10;
if(i==x[0])x[0]++;
}
}
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin>>s>>n;
ct[0]=1,ct[1]=1;
for(int i=1;i<=n;i++)cin>>f[i].x>>f[i].y;
for(int i=0;i<s.length();i++){
tct=0;
memset(vis,false,sizeof(vis));
dfs(s[i]);
HPNmul(ct,tct);
}
for(int i=ct[0];i>=1;i--)cout<<ct[i];
}