「East!_XX」手机号码
Description
众所周知,天朝泱泱五千年的文化积淀下,人们在数字上尤为挑剔。很多人认为,不吉利的数字会导致流年困顿。「阿弥陀佛,作为社会主义接班人,我们应该相信科学,远离迷信!」
在天朝,不同的人读手机号码有不同的方式(见右图)。人们选择手机号码时,为了照顾“不吉利数字恐惧症”患者,总会希望任何人报自己的电话号码时都不会连续说出来不吉利数字。
例如,很多天朝子民认为5914是一串很不吉利的号码,因此尾号为5914的手机号码理所当然地被众人所避忌。而号码188-8859-1488却不是一个不吉利号码,因为无论使用右图中的哪一种方式去读,5914均会被拆分开来。
现在,我们想知道的是,在天朝,有多少电话号码能被人们所接受。
* 常识:在中国,民用手机号段均以1开头。
Input
第一行输入一个正整数N,表示有N个不吉利的数字串。
接下来N行,每行一个5位以内的数字串,表示一个不吉利的号码。
Output
一个正整数,表示并非不吉利的号码总数。
Sample I/O
Sample Input |
Sample Output |
1 5914 |
9996000100 |
Hint
对于20% 的数据,N ≤ 2;
对于100% 的数据,N ≤ 100;
题解
出题人Eolv:
对右图所示四种读电话号码的方式进行总结,可得到信息:
符合题意的电话号码中第1~4位、第4~7位、第5~8位、第7~11位均不包含不吉利数字串。
令f[i,x]表示对于前i位号码,以数字串x结尾的方案数。显然,只需要依次求出f[4,0…9]、f[7,000…999]、f[8,00…99]、f[11,00000…99999]即可统计出答案。由于不吉利数字串的总数较少,转移时直接枚举所有的情况即可。也可以建立AC自动机对这一过程进行优化。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 |
#include<set> #include<map> #include<ctime> #include<queue> #include<cmath> #include<cstdio> #include<vector> #include<cstring> #include<cstdlib> #include<iostream> #include<algorithm> #define inf 2000000000 #define mp make_pair #define pa pair<ll,ll> #define ll long long using namespace std; ll read() { ll x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } ll ans; int n; int f[15][100005]; char ch[105][10]; bool mark[100005]; int getint(char a[]) { int n=strlen(a+1),ans=0; for(int i=1;i<=n;i++) ans=ans*10+a[i]-'0'; return ans; } bool del(int x) { if(mark[x]||mark[x%10]||mark[x%100]||mark[x%1000]||mark[x%10000])return 1; if(x>=10)if(del(x/10))return 1; return 0; } int main() { n=read(); for(int i=1;i<=n;i++) { scanf("%s",ch[i]+1); mark[getint(ch[i])]=1; } f[1][1]=1; for(int i=1;i<=10;i++) for(int j=0;j<=99999;j++) if(f[i][j]) { if((i==4||i==7||i==8)&&del(j%10000)) continue; for(int k=0;k<=9;k++) f[i+1][(j*10+k)%100000]+=f[i][j]; } for(int j=0;j<=99999;j++) { if(del(j))continue; ans+=f[11][j]; } printf("%lld\n",ans); return 0; }//4 7 8 11 |