【AC代碼】
#include <iostream>#include <cstdio> //cstdio內有scanf()函數#include <cstring> //cstring內有strlen(),memset()函數using namespace std;char num[32]; //字符型num數組用于輸入做變換的巨大數字,它最多長達31位數int value[32]={0,1}; //value[1]設為1,既是乘法的開始,也是k=0這種情況的特殊結果int change[10][10]; //bool型的change[i][j]儲存是否存在從i向j的變換int node[10]; //bool型的node[n]記錄n這種變換結果是否被記錄過int factor; //factor記錄每一位上可能的變換結果的總數,所有位上的factor相乘得到的即是所求的種類總數int multilen=1; //變化的multilen反映的是當前高精度乘法結果的位數void DFS(int n) //深度優先搜索一個數字{ int j; if(node[n]) //如果node[n]為1,表示n這種變換結果已被記錄過 return ; //這時再向下搜索得到的也只是與之前重復的情況,這時候就不必再DFS,只要返回上一個DFS(調用該DFS的DFS) else //如果node[n]為0,表示n這種結果沒有被記錄過 { node[n]=1; //下面要記錄它,將node[n]設為1 factor++; //用全局變量factor因子記錄這種情況 } for(j=0;j<=9;j++) //對于這10個數字j if(change[n][j]) //如果存在從n向j的變換 DFS(j); //那么我們就變換,搜索變換后的j}void multiply() //高精度乘法,將因子factor乘入數組value[]{ int carry=0; //carry表示每次乘法需要進位的數字 for(int i=1;i<=multilen;i++) //從第一位到最后一位每一位都要乘 { value[i]=value[i]*factor+carry; //乘上因子factor,再加上上一位留下的進位數carry carry=value[i]/10; //carry再變成當前這一位對下一位產生的進位數 value[i]%=10; //進位后,本位當然要對10取余 } if(carry>0) //如果到最后一位也乘完,還存在向下一位的進位數carry value[++multilen]=carry; //那么總位數就要增加一位,并將進位數放進去}int main(){ int k,i,j,length; //length將儲存num的長度 scanf("%s%d",num,&k); //用scanf以跳過空格 memset(change,0,sizeof(change)); //change[i][j]為0時表示不存在從i向j的變換,先清零,再在后面賦1 while(k--) { cin>>i>>j; change[i][j]=1; //change[i][j]為1時表示存在從i向j的變換 } length=strlen(num); //這樣做僅避免反復的求長度運算 for(i=0;i<length;i++) //遍歷輸入數字的每一位數 { memset(node,0,sizeof(node)); //每次將DFS節點數組node[]清空 factor=0; //factor臨時儲存每一位的因子 DFS(num[i]-'0'); //對每一位深度優先搜索能做多少次變換 multiply(); //將因子相乘(高精度)放入數組value[] } for(i=multilen;i>=1;i--) cout<<value[i]; //從高位到低位輸出每一位數return 0;}
新聞熱點
疑難解答