题意:问你在所有包含666的数中,第n大的是多少。(1 ≤ n ≤ 50,000,000) 。开头几个是666, 1666, 2666, 3666, 4666, 5666…
题解:
这题可以用AC自动机,不知道这个怎么做。。
用了数位DP。
第一道自己好好调出来的数位DP。。哭泣
(一)先用DP预处理出含有666的k位数一共有多少个,不含有666的k位数一共有多少个。只用求一边就可以,另一边用总数来减。
然后for一遍,判断出第n大的是多少位数。
//d[0][i] 第一位不是6的i位数不含666总方案数
//d[1][i] 第一位是6...
//d[2][i] 连续两个6...
//d[3][i] 不含666的i位数的总方案数
//d[4][i] 含有666的i位数...
(二)填数(从左往右)。填的时候要记录前两位是什么。
分两种情况:
1.填的数中已经有666。则后面的位可以填有666和没有666的数。
2.没有666。
这个再分两种 (1)现在不要填6-->则后面必须有666
(2)现在填6 如果是xx6,则后面可以是66xxxx或含有666的数;如果是x66,则后面是6xxx或者66xxx或者含有666的数。如果是xx6,则后面是66xxx或者含有666的数。
1 #include<cstdio> 2 #include<cstdlib> 3 #include<cstring> 4 #include<iostream> 5 #include<queue> 6 using namespace std; 7 8 typedef long long LL; 9 const int N=50000010,D=10; 10 LL d[5][20]; 11 int n,ans[20]; 12 //d[0][i] 第一位不是6的i位数不含666总方案数 13 //d[1][i] 第一位是6... 14 //d[2][i] 连续两个6... 15 //d[3][i] 不含666的i位数的总方案数 16 //d[4][i] 含有666的i位数... 17 18 int main() 19 { 20 freopen("a.in","r",stdin); 21 freopen("a.out","w",stdout); 22 memset(d,0,sizeof(d)); 23 memset(ans,0,sizeof(ans)); 24 LL sum=100; 25 d[0][1]=9;d[1][1]=1;d[2][1]=0;d[3][1]=10;d[4][1]=0; 26 d[0][2]=9*10;d[1][2]=9;d[2][2]=1;d[3][2]=10*10;d[4][2]=0; 27 for(int i=3;i<=D;i++) 28 { 29 d[0][i]=9*d[3][i-1]; 30 d[1][i]=d[0][i-1]; 31 d[2][i]=d[1][i-1]; 32 d[3][i]=d[0][i]+d[1][i]+d[2][i]; 33 sum*=10; 34 d[4][i]=sum-d[3][i]; 35 } 36 int T; 37 scanf("%d",&T); 38 while(T--) 39 { 40 scanf("%d",&n); 41 int k=0; 42 for(LL i=3;i<=D;i++) 43 if(d[4][i]>n) {k=i;break;} 44 int now=0,a=0,b=0; 45 bool ok=0; 46 for(int i=1;i<=k;i++) 47 { 48 if(i==k) 49 { 50 if(!ok) ans[k]=6; 51 else ans[k]=n-now-1; 52 break; 53 } 54 bool bk=0; 55 for(int j=0;j<=9;j++) 56 { 57 if(!ok) 58 { 59 if(j!=6) 60 { 61 if(now+d[4][k-i]<n) now+=d[4][k-i]; 62 else ans[i]=j,bk=1; 63 } 64 else 65 { 66 if(a==6 && b==6) 67 { 68 if(now+d[3][k-i]+d[4][k-i]<n) now+=d[3][k-i]+d[4][k-i]; 69 else ans[i]=j,bk=1,ok=1; 70 } 71 else if(a!=6 && b==6) 72 { 73 if(now+d[1][k-i]+d[2][k-i]+d[4][k-i]<n) now+=d[1][k-i]+d[2][k-i]+d[4][k-i]; 74 else ans[i]=j,bk=1; 75 } 76 else //这里原本打了a、b都不等于6,WA,应该是b不等于6就可以了。 77 { 78 if(now+d[2][k-i]+d[4][k-i]<n) now+=d[2][k-i]+d[4][k-i]; 79 else ans[i]=j,bk=1; 80 } 81 } 82 } 83 else 84 { 85 if(now+d[3][k-i]+d[4][k-i]<n) now+=d[3][k-i]+d[4][k-i]; 86 else ans[i]=j,bk=1; 87 } 88 if(bk) break; 89 } 90 a=ans[i-1],b=ans[i]; 91 } 92 bool fir=0; 93 for(int i=1;i<=k;i++) 94 { 95 if(fir==0 && ans[i]==0) continue; 96 if(fir==0 && ans[i]!=0) fir=1; 97 if(fir) printf("%d",ans[i]); 98 } 99 if(T) printf(" "); 100 } 101 return 0; 102 }