bnuoj 4359无爱编号(数位dp)

众所周知,拉手网有许多客户,由于客户数量实在过于庞大,因此拉手网希望为每位客户进行编号以便更好的为客户服务。每个编号为一个由‘0’~‘9’组成的N位数字。考虑到很多人不喜欢数字4和数字13,因此我们称包含4或包含13的编号为无爱编号,如134、84、121351都是无爱编号,123则不是无爱编号。现在我们希望知道,所有N位的编号中,刨除掉无爱编号后剩余的编号数量。这个编号数量可能很大,我们只要知道结果的最后8位即可。

Input

 输入的第一行是一个整数T,表示数据组数。

以下 T 行每行一个整数 N 1 N 1000000 ),表示编号的位数。

Output

 对于每组数据,输出一个8位整数表示编号数量的最后8位。若编号数量不足8位则用前导零填充。

Sample Input

2
1
2

Sample Output

00000009
00000080

Source

第九届北京师范大学程序设计竞赛决赛

Author

temperlsyer


#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <string>
#include <cmath>
#include <set>
#include <queue>
#include <algorithm>
#include <vector>
#include <stack>
const double PI = acos(-1.0);
using namespace std;
#define esp  1e-8
const int inf = 99999999;
const int mod = 100000000;
//freopen("in.txt","r",stdin); //输入重定向,输入数据将从in.txt文件中读取
//freopen("out.txt","w",stdout); //输出重定向,输出数据将保存在out.txt文件中
long long dp[1000005][3];
//dp[i][0] 为长度<=i的合法个数
//dp[i][1] 为长度<=i,首位为3的合法个数
//dp[i][2] 为长度<=i的非法个数
void init()
{
	memset(dp, 0, sizeof(dp));
	dp[0][0] = 1;
	for (int i = 1; i <= 1000001; ++i)
	{
		dp[i][0] = (dp[i - 1][0] * 9 - dp[i - 1][1] ) % mod;
		dp[i][1] = dp[i - 1][0] % mod;
		dp[i][2] = (dp[i - 1][0] + dp[i - 1][1] + dp[i - 1][2] * 10) % mod;
	}
}
int main()
{
	int t, n;
	init();
	scanf("%d", &t);
	while (t--)
	{
		scanf("%d", &n);
		printf("%08lld\n", (dp[n][0] + mod)% mod);//注意先加mod再取余,防止变负;
	}
}



你可能感兴趣的:(bnuoj 4359无爱编号(数位dp))