正题
题目链接:http://poj.org/problem?id=3208
题目大意
求第X个有3个连续的6的数。
解题思路
用fi,j(j<3)fi,j(j<3)表示i位,已经有j个6的方案总数。然后fi,3fi,3表示i位的魔鬼数的总数。
然后动态转移方程。
fi,0=9∗(fi−1,0+fi−1,1+fi−1,2)fi,0=9∗(fi−1,0+fi−1,1+fi−1,2)
只要一个不是6的数就能间断他们
fi,1=fi−1,0fi,1=fi−1,0
fi,2=fi−1,1fi,2=fi−1,1
加一个6
fi,3=fi−1,2+10∗fi−1,3fi,3=fi−1,2+10∗fi−1,3
上一位加任意一个数或两个六的情况下加一个6。
然后试填就好了
code
#include<cstdio>
#include<algorithm>
using namespace std;
long long f[21][4];
int t,n,m;
int main()
{f[0][0]=1;for(int i=1;i<=20;i++){f[i][0]=9*(f[i-1][0]+f[i-1][1]+f[i-1][2]);f[i][1]=f[i-1][0];f[i][2]=f[i-1][1];f[i][3]=f[i-1][2]+10*f[i-1][3];}//dpscanf("%d",&t);for(int ti=1;ti<=t;ti++){scanf("%d",&n);for(m=3;f[m][3]<n;m++);//判断位数for(int i=m,k=0;i;i--)//枚举填入位数{for(int j=0;j<=9;j++)//填入j{long long cnt=f[i-1][3];//判断位数if(j==6||k==3)for(int l=max(3-k-(j==6),0);l<3;l++)cnt+=f[i-1][l];//特判统计if(cnt<n)n-=cnt;//超过这个位数else{if(k<3)//位数不足3时特判特殊判断{k+=(j==6);k*=(j==6);}printf("%d",j);//输出break;//填完了} }}printf("\n");}
}