数位DP POJ3208 Apocalypse Someday

题目大意

求第X个有3个连续的6的数。

解题思路

#include<iostream>
#include<algorithm>
using namespace std;
int t,n,m,k;
long long f[21][4];
void work()//预处理!!! 
{
    f[0][0]=1;
     for(int i=0;i<20;i++)
	 {
         for(int j=0;j<3;j++)
		 {
             f[i+1][j+1]+=f[i][j];
             f[i+1][0]+=f[i][j]*9;
         }
         f[i+1][3]+=f[i][3]*10;
     }
}
 int main()
 {
     work();
     scanf("%d",&t);
     while(t)
	 {
         t--;
         scanf("%d",&n);//题目中第几个魔鬼数 
         for(m=3;f[m][3]<n;m++);//求出第n个魔鬼数的位数!!! 
         k=0;
         for(int i=m;i>0;i--)
		 {    //从小到大枚举第i位数字!!! 
             for(int j=0;j<=9;j++)
			 {//求出后面i-1位有多少填法能让整个数是魔鬼数 
                 long long tmp=f[i-1][3];
                 if(k==3||j==6)
                    for(int p=max(0,3-k-(j==6?1:0));p<3;p++)
                        tmp+=f[i-1][p];
                 if(tmp<n)  n-=tmp; //如果cnt比n小,说明第n个魔鬼数的第i位比j更大!!! 
                 else//否则,第i位就应该为 j 
				 {
                     if(k<3&&j==6) k++;//k记录当前位已有连续几个连续6 
                     if(k<3&&j!=6) k=0;
                     printf("%d",j);
                     break;
                 }
             }
         }
         printf("\n");
     }
     return 0;
}

猜你喜欢

转载自blog.csdn.net/mlm5678/article/details/82635131