poj3208

题面:

古代人认为666是属于魔鬼的数。

不但如此,只要某数字的十进制表示中有三个连续的6,古代人也认为这是个魔鬼的数,比如666,1666,6663,16666,6660666等等。

古代典籍中经常用“第X小的魔鬼的数”来指代这些数,这给研究人员带来了极大的不便。

现在请编写一个程序,可以实现输入X,输出对应的魔鬼数。

输入格式

第一行包含整数T,表示共有T组测试数据。

每组测试数据占一行,包含一个整数X。

输出格式

每组测试数据占一行,输出一个魔鬼数。

数据范围

1T10001≤T≤1000,
1X51071≤X≤5∗107

输入样例:

3
2
3
187

输出样例:

1666
2666
66666
题解:
设f[i][3]表示由i位数字构成的魔鬼数有多少,f[i][j](0<=j<=2)表示由i位数字构成的,开头已经由连续j个6的非魔鬼数有多少个。在计算f的时候,允许前导0的存在。
考虑第i位(最高位)是什么数字,容易得到转移方程
f[i][0]=9*(f[i-1][0]+f[i-1][1]+f[i-1][2])//但i位前面无连续的6时,i-1位前有几个都可以,第i位可以填除6以外的任何数
f[i][1]=f[i-1][0]//第i位填6
f[i][2]=f[i-1][1]//第i位填6
f[i][3]=f[i-1][2](第i位填6)+10*f[i-1][3](第i位填任何数)
然后通过“试填法“从最高位一位一位确定具体的数,同时记录当前末尾已经有连续的k个6(可以与开头由3-k的非魔鬼数构成新的魔鬼数统计进去)
从小到大枚举当前位填什么数字,通过预处理的F数组可以直接计算出后边的数位有多少种填法可以得到魔鬼数,与x比较即可
代码:
 1 #include<iostream>
 2 #include<cstring>
 3 #include<cmath>
 4 using namespace std;
 5 long long f[21][4];
 6 int t,n,m;
 7 void pre_work()
 8 {
 9     f[0][0]=1;
10     for(int i=0;i<20;i++)
11     {
12         for(int j=0;j<3;j++)
13         {
14         f[i+1][j+1]+=f[i][j];
15         f[i+1][0]+=9*f[i][j];
16        }
17        f[i+1][3]+=f[i][3]*10;
18     }
19 }
20 int main()
21 {
22     pre_work();//预处理
23     scanf("%d",&t);
24     //cin>>t;
25     while(t--)
26     {
27         //printf("%lld
",f[3][3]);
28         scanf("%d",&n);
29         for(m=3;f[m][3]<n;m++);//确定位数
30         for(int i=m,k=0;i;i--)
31         {
32             for(int j=0;j<=9;j++)
33             {
34                 long long cnt=f[i-1][3];//i-1位魔鬼数
35                 if(j==6||k==3)//求由前l(0<=l<=2)个6开头的非魔鬼数与已经出现的3-l个6构成的魔鬼数个数
36                 for(int l=max(3-k-(j==6),0);l<3;l++)
37                 cnt+=f[i-1][l];
38                 if(cnt<n)
39                 n-=cnt;
40                 else
41                 {
42                     if(k<3)//如果已经出现了连续的3个6均可构成魔鬼数
43                     {
44                         if(j==6)k++;
45                         else
46                         k=0;
47                     }
48                     printf("%d",j);
49                     break;
50                 }
51             }
52         }
53         printf("
");
54     }
55      return 0;
56 }
原文地址:https://www.cnblogs.com/flyljz/p/11727507.html