1. 程式人生 > >BZOJ4521: [Cqoi2016]手機號碼

BZOJ4521: [Cqoi2016]手機號碼

Description

人們選擇手機號碼時都希望號碼好記、吉利。比如號碼中含有幾位相鄰的相同數字、不含諧音不 吉利的數字等。手機運營商在發行新號碼時也會考慮這些因素,從號段中選取含有某些特徵的號 碼單獨出售。為了便於前期規劃,運營商希望開發一個工具來自動統計號段中滿足特徵的號碼數 量。 工具需要檢測的號碼特徵有兩個:號碼中要出現至少3個相鄰的相同數字,號碼中不能同 時出現8和4。號碼必須同時包含兩個特徵才滿足條件。滿足條件的號碼例如:13000988721、 23333333333、14444101000。而不滿足條件的號碼例如:1015400080、10010012022。 手機號碼一定是11位數,前不含前導的0。工具接收兩個數L和R,自動統計出[L,R]區間 內所有滿足條件的號碼數量。L和R也是11位的手機號碼。

Input

輸入檔案內容只有一行,為空格分隔的2個正整數L,R。 10^10 < =  L < =  R < 10^11

Output

輸出檔案內容只有一行,為1個整數,表示滿足條件的手機號數量。

Sample Input

12121284000 12121285550

Sample Output

5
樣例解釋
滿足條件的號碼: 12121285000、 12121285111、 12121285222、 12121285333、 12121285550

啊啊啊這麼多天終於有一道不看題解做出來的題了 數位dp,考慮用記憶化搜尋的方式實現... 狀態的定義:
具體實現看程式碼吧,總算是從剛開始七零八落的思維一點點構建出來了 需要提醒的一點是,對於9999999999(十個9)來說,要強制轉化成09999999999,即十一位數 因為這個dp是包含前導零的 前面多填一個0會多增加許多貢獻(兩個零連在前頭)有57977624個(別問我怎麼知道的(;´д`)ゞ    
 1 #include<cstdio>
 2 #include<cstring>
 3 #define ll long long
 4 using namespace
std; 5 ll L,R; 6 int a[20],tot; 7 ll F[12][2][2][5][12][15]; 8 ll ksm(ll x,ll t){ 9 ll ans=1; 10 for(;t;t>>=1,x=(x*x))if(t&1)ans=(ans*x); 11 return ans; 12 } 13 ll dfs(int i,bool f,int t,int x,int k,int w){ 14 //µÚiλ¼°ÒÔºó¶¼Ã»Ìf¸ü¸ßµÄλÊÇ·ñ¶¼½ôÌù×ÅR,ĩβÁ¬ÐøÊý×ÖÊýÁ¿ÊÇk 15 //tÊÇ·ñÒѾ­º¬ÓÐ3Á¬£¬x=-1 ÎÞ8ÎÞ4£¬x=0ÓÐ4ÎÞ8£¬x=1ÓÐ8ÎÞ4 16 //wÉÏÒ»´ÎĩβÊý×ÖÊǼ¸ 17 if(F[i][f][t][x+1][k][w+1]!=-1)return F[i][f][t][x+1][k][w+1]; 18 ll ans=0; 19 if(i==0){ 20 ans=t; 21 } 22 else if(f==0&&t==1){ 23 if(x==0||x==1)ans=ksm(9,i); 24 else ans=ksm(9,i)*2-ksm(8,i); 25 } 26 else if(f==0){ 27 for(int j=0;j<=9;j++){ 28 if(j==4&&x!=1) 29 ans+=dfs(i-1,f,t|((w==j?k+1:1)>=3),0,w==j?k+1:1,j); 30 else if(j==8&&x!=0) 31 ans+=dfs(i-1,f,t|((w==j?k+1:1)>=3),1,w==j?k+1:1,j); 32 else if(j!=8&&j!=4) 33 ans+=dfs(i-1,f,t|((w==j?k+1:1)>=3),x,w==j?k+1:1,j); 34 } 35 } 36 else{ 37 for(int j=0;j<a[i];j++){ 38 if(j==4&&x!=1) 39 ans+=dfs(i-1,0,t|((w==j?k+1:1)>=3),0,w==j?k+1:1,j); 40 else if(j==8&&x!=0) 41 ans+=dfs(i-1,0,t|((w==j?k+1:1)>=3),1,w==j?k+1:1,j); 42 else if(j!=8&&j!=4) 43 ans+=dfs(i-1,0,t|((w==j?k+1:1)>=3),x,w==j?k+1:1,j); 44 } 45 if(a[i]==4&&x!=1) 46 ans+=dfs(i-1,f,t|((w==a[i]?k+1:1)>=3),0,w==a[i]?k+1:1,a[i]); 47 else if(a[i]==8&&x!=0) 48 ans+=dfs(i-1,f,t|((w==a[i]?k+1:1)>=3),1,w==a[i]?k+1:1,a[i]); 49 else if(a[i]!=8&&a[i]!=4) 50 ans+=dfs(i-1,f,t|((w==a[i]?k+1:1)>=3),x,w==a[i]?k+1:1,a[i]); 51 } 52 F[i][f][t][x+1][k][w+1]=ans; 53 return ans; 54 } 55 ll work(ll R){ 56 memset(F,-1,sizeof(F)); 57 tot=0; 58 while(R){ 59 a[++tot]=R%10; 60 R/=10; 61 } 62 if(tot==10)a[11]=0; 63 return dfs(11,1,0,-1,0,-1); 64 } 65 int main(){ 66 scanf("%lld%lld",&L,&R); 67 printf("%lld",work(R)-work(L-1)); 68 return 0; 69 }
View Code