您的位置:首页 > 其它

Codeforces 259 D 数位DP + 搜索

2013-01-16 15:16 295 查看
http://www.codeforces.com/contest/259/problem/D

数位DP可以写成递归和非递归两种:

递归:

#include <cstdio>
#include <cstring>
#include <algorithm>
#define LL __int64
const LL mod = 1000000007;
LL dp[11], ans;
int len;
char a[11];

void add(int dep, int dig, int num)
{
if(!dep)
{
dp[dig] += num;
return;
}
add(dep-1, dig+1, num*2);
add(dep-1, dig, num*8);
}
void dfs(int dep, int sum, int tot)
{
int i;
if(sum >= len) return;
if(dep == 6)
{
for(i = sum+1; i <= len; i++)
ans = (ans + tot*dp[i])% mod;
return;
}
for(i = 0; i < len; i++)
{
if(dp[i])
{
dp[i]--;
dfs(dep+1, sum+i, tot*(dp[i]+1)%mod);
dp[i]++;
}
}
}
int main()
{
int i, j, t = 0;
len = strlen(gets(a));
for(i = 0; i < len; i++)
{
for(j = 0; j < a[i] - '0'; j++)
{
if(j == 4 || j == 7)
add(len-1-i, t+1, 1);
else
add(len-1-i, t, 1);
}
if(a[i] == '4' || a[i] == '7')
t++;
}
dp[t]++, dp[0]--;
//  for(i = 0; i <= 9; i++)
//      printf("%d\n", dp[i]);
dfs(0, 0, 1);
printf("%I64d\n", ans);
return 0;
}


非递归:

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define LL __int64
LL dp[11][11], f[11];
int a[11], n;
const LL mod = 1000000007;
void init()
{
int i, j, k;
dp[1][1] = 2; dp[1][0] = 8;
for(i = 2; i <= 9; i++)
{
for(j = 1; j <= i; j++)
dp[i][j] = (dp[i-1][j] * 8 + dp[i-1][j-1] * 2) % mod;
dp[i][0] = dp[i-1][0] * 8 % mod;
}
//	for(i = 2; i <= 9; i++)
//		for(j = 0; j <= i; j++)
//			printf("dp[%d][%d] = %I64d\n", i, j, dp[i][j]);
}

LL ans;
int l;
void dfs(int dep, int sum, LL tot)
{
int i;
if(dep == 6)
{
for(i = sum+1; i <= l; i++)
ans = (ans + tot * f[i]) % mod;
return;
}
if(sum >= l) return;
for(i = 0; i <= l; i++)
if(f[i])
{
f[i]--;
dfs(dep+1, sum+i, tot*(f[i]+1)%mod);
f[i]++;
}
}
int main()
{
init();
int i, j, k;
scanf("%d", &n);
while(n) {a[l++] = n % 10; n /= 10;}
//处理位数< l 的 数
for(j = 0; j <= l-1; j++)
f[j] = (f[j] + dp[l-1][j]) % mod;
//	for(i = 0; i <= 9; i++)
//		printf("f[%d] = %I64d\n", i, f[i]);
LL cnt = 0;
for(i = l-1; i >= 0; i--) // 每一位降位处理
{
for(j = (i == l-1 ? 1 : 0); j < a[i]; j++) // 注意首位不能为0,很容易出错
{
if(j==4 || j==7)
for(k = cnt+1; k <= cnt+i+1; k++) // 注意lucky number 的 范围
f[k] = (f[k] + (i ? dp[i][k-1-cnt] : 1)) % mod;
else
for(k = cnt; k <= cnt+i; k++) // 注意lucky number 的 范围
f[k] = (f[k] + (i ? dp[i][k-cnt] : 1)) % mod;
}

//	for(j = 0; j <= 9; j++)
//	printf("i = %d f[%d] = %I64d\n", i, j, f[j]);
cnt += (a[i]==4 || a[i]==7);
}
f[cnt]++;
if(l > 1)f[0]--; //特别注意 输入的数只有一位的时候, 我们没有 把 0 算进去,所以不用去零。
//	for(i = 0; i <= 9; i++)
//		printf("f[%d] = %I64d\n", i, f[i]);
dfs(0, 0, 1);
printf("%I64d\n", ans);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: