CF258B
Posted repulser
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CF258B相关的知识,希望对你有一定的参考价值。
CF258B
题意:
7个人在 $ [1,m] $ 区间内取数,求第一个人选的数的4和7的个数大于其他人的4和7个数总和的方案数。
解法:
要求输入的 $ m $ 可以很大,而且需要按位考虑每隔人的贡献,所以考虑数位DP。
设 $ f[i][j] $ 表示到第 $ i $ 位,有 $ j $ 个数是 $ 4 和 7 $ 的方案数,再利用dfs进行转移就行。
CODE :
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define LL long long
const LL MOD = 1e9+7;
LL final,dp[16][16],c[16];
int bit[16],l,cnt,tot,m;
int work(int m, int n)
cnt = tot = l = 0;
for (; m; m /= 10) bit[++l] = m % 10;
for (int i = l; i && tot <= n; --i)
for(int j = 0 ; j < bit[i] ; j++)
if (j == 4 || j == 7)
if (tot < n) cnt += dp[i - 1][n - tot - 1];
else cnt += dp[i - 1][n - tot];
if (bit[i] == 4 || bit[i] == 7) ++tot;
if(tot == n) ++cnt;
if(n == 0) --cnt;
return cnt;
void dfs(int t, int now, int lim, LL ans)
if (t == 6) (final += ans) %= MOD;
else
for (int i = 0; i <= 9 && i + now < lim; ++i)
if (c[i])
c[i]--;
dfs(t + 1, now + i, lim, ans * (c[i] + 1) % MOD);
c[i]++;
int main()
scanf("%d", &m);
dp[0][0] = 1;
for(int i = 0 ; i <= 9 ; i++)
for(int j = 0 ; j <= i ; j++)
dp[i + 1][j + 1] += dp[i][j] * 2;
dp[i + 1][j] += dp[i][j] * 8;
for(int i = 0 ; i <= 9 ; i++) c[i] = work(m, i);
for(int i = 0 ; i <= 9 ; i++)
if (c[i])
--c[i];
dfs(0, 0, i, (c[i] + 1) % MOD);
++c[i];
printf("%lld \n", final);
//system("pause");
return 0;
以上是关于CF258B的主要内容,如果未能解决你的问题,请参考以下文章
CodeForces 258B Little Elephant and Elections
Little Elephant and Elections CodeForces - 258B