1. 程式人生 > >產生數

產生數

格式 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; }

產生數