產生數
阿新 • • 發佈:2018-03-11
格式 strlen 乘法 -m std 可能 amp 鍵盤 復制
題目描述
給出一個整數 n(n<10^30) 和 k 個變換規則(k<=15)。
規則:
一位數可變換成另一個一位數:
規則的右部不能為零。
例如:n=234。有規則(k=2):
2->5 3->6 上面的整數 234 經過變換後可能產生出的整數為(包括原數):
234 534 264 564 共 4 種不同的產生數
問題:
給出一個整數 n 和 k 個規則。
求出:
經過任意次的變換(0次或多次),能產生出多少個不同整數。
僅要求輸出個數。
輸入輸出格式
輸入格式:
鍵盤輸人,格式為:
n k x1 y1 x2 y2 ... ...
xn yn
輸出格式:
屏幕輸出,格式為:
一個整數(滿足條件的個數):
輸入輸出樣例
輸入樣例#1: 復制234 2 2 5 3 6輸出樣例#1: 復制
4
【題解】傳遞閉包+高精
DFS會TLE,所以想到可能性就要想到乘法原理
#include<cstdio> #include<cstring> int d[20][20]= {0}; int num[333],k,ans[33]= {0,1},len=1,cnt[10]= {0}; char s[33]; void cal(int b) { for(int i=1; i<=len; i++) ans[i]*=b;for(int i=1; i<=len; i++) { ans[i+1]+=ans[i]/10; ans[i]%=10; } while(ans[len+1]>0)len++; while(ans[len]==0&&len>1)len--; } int main() { int u,v; scanf("%s%d",s+1,&k); for(int i=1; i<=strlen(s+1); i++) num[i]=s[i]-‘0‘; for(int i=1; i<=k; i++) { scanf("%d%d",&u,&v); d[u][v]=true; } for(int i=0; i<=9; i++)d[i][i]=true; for(int k=0; k<=9; k++) for(int i=0; i<=9; i++) for(int j=0; j<=9; j++) d[i][j]|=d[i][k]&d[k][j]; for(int i=0; i<=9; i++) for(int j=0; j<=9; j++)cnt[i]+=d[i][j]; for(int i=1; i<=strlen(s+1); i++) if(cnt[num[i]]) cal(cnt[num[i]]); for(int i=len; i>=1; i--) putchar(ans[i]+‘0‘); puts(""); return 0; }
產生數