P1037 产生数(洛谷)

题目传送门

  最开始错误的思路是对整条字串进行dfs,看一位dfs进入下一位,这是没有充分理解题意的后果
 
  核心解题思路:不要被这些规则变来变去搞混了,我们需要将原问题进行切割成小的子问题去分析。例如此处我们将每一位数都当做一个独立单位,首先求出在这个位置上有多少种可以存在的数的种类(0~9)。而这些独立单位(位置)互不相同,彼此独立,因此求出总的可变换的数的总数则是每个位置上的数的种类的累乘。对每一位上的数操作时,把变换的规则当做是点与点的连接(一共有10个点位0~9)。因此想要访问所有能走的点(有多少点则有个种类的数),因此这一遍历全部图的思想符合dfs的性质

  注意:在数的第一个位置上,我们假设0的存在是合法的,比如0123实际上是123,但它也带来了一个新的数字,因此种类也会增加
 
 
实现代码:
 
 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define lll __uint128_t
 4 
 5 char s[100];        //用于储存整数 
 6 int memory[100]={0};            //用于数有多少种变换种类    实质是一个优化,记忆化储存 
 7 lll ans;             //用于储存数的种类 
 8 int num=0;            //记录每个位置上有多少种类数 
 9 int flag[100]={0};        //用于dfs中标志     同样直接拿字符'0'~'9'当做下标 
10 int k=0;                //规则数 
11 char a[20],b[20];            //储存变换规则
12  
13 void out(lll x){//int128输出要自己写 
14     if(x>9)out(x/10);
15     putchar(x%10+48);
16 }
17 void dfs(char index){
18     flag[index]=1;        //走过标记为1
19     num++;                //访问到一个点就加一
20     
21     for(int i=1;i<=k;i++){
22         if(index==a[i]){
23             if(flag[b[i]])    continue;        //访问过                
24             dfs(b[i]);
25             //这里不能加上回溯,因为不会重复访问同一个点 
26         } 
27     } 
28     return ;
29     
30 } 
31 int main(){
32     ios::sync_with_stdio(false);        //加快数据的输入和输出 
33     cin.tie(0);
34     cout.tie(0);
35     ans=1;        //初始化为1
36     
37     cin>>s>>k;
38     for(int i=1;i<=k;i++){
39         cin>>a[i]>>b[i];
40     }
41     
42     for(int i=0;s[i]!='\0';i++){        //对于每一位数去操作 
43         num=0;
44         if(memory[s[i]]){                    //直接拿ascii码当下标,懒得去转为数字 
45             num=memory[s[i]];                //表示之前已经搜过相同的数了,结果存在数组a中 
46         }else{                            //表示没搜过第一次搜 
47             memset(flag,0,sizeof(flag));
48             dfs(s[i]); 
49             memory[s[i]]=num;                //储存下来 
50         }
51         ans*=num;
52     } 
53     out(ans);        //输出种类数 
54     return 0;
55 }

补充说明:__uint128_t是一个较大的类型,而且符合gcc标准,在很多oj平台上可以使用。但其输出函数不能用cout或者printf,需要自己重写。详细解释见:这里。

如果不用此类型,则需要高精度乘法算法来实现程序。

posted @ 2020-03-31 20:28  neverstopcoding  阅读(246)  评论(0编辑  收藏  举报