Codeforces-258B Little Elephant and Elections

20 篇文章 0 订阅
20 篇文章 0 订阅
B. Little Elephant and Elections
time limit per test
2 seconds
memory limit per test
256 megabytes

There have recently been elections in the zoo. Overall there were 7 main political parties: one of them is the Little Elephant Political Party,6 other parties have less catchy names.

Political parties find their number in the ballot highly important. Overall there arem possible numbers: 1, 2, ..., m. Each of these 7 parties is going to be assigned in some way to exactly one number, at that, two distinct parties cannot receive the same number.

The Little Elephant Political Party members believe in the lucky digits 4 and 7. They want to evaluate their chances in the elections. For that, they need to find out, how many correct assignments are there, such that the number of lucky digits in the Little Elephant Political Party ballot number is strictly larger than the total number of lucky digits in the ballot numbers of 6 other parties.

Help the Little Elephant Political Party, calculate this number. As the answer can be rather large, print the remainder from dividing it by1000000007 (109 + 7).

Input

A single line contains a single positive integer m(7 ≤ m ≤ 109) — the number of possible numbers in the ballot.

Output

In a single line print a single integer — the answer to the problem modulo 1000000007 (109 + 7).

Sample test(s)
Input
7
Output
0
Input
8
Output
1440

————————————————————集训22.3的分割线————————————————————

前言:自己做难、看了题解就不难了……

思路:把数字4或7当做是幸运值+1,目标是从1~n选出7个数,使得其中一个数的幸运值严格大于其余6个数的幸运值之和,求所有的方案数。

先把问题划分成三个子问题:

1. n以内所有数的幸运值

2. 选出7个数字

3. 7个数字的组合方案数

对于第一个问题: 一开始我找不到正确的姿势去数位DP,看了题解我明白了,第一个问题其实并不是n以内所有数的幸运值,而是:
所有可能的幸运值对应的数字的个数
我不可能dfs所有数字的幸运值,内存、时限都不允许,但是10^9以内的数字,幸运值只可能是0~9。我只需枚举可能的幸运值,然后dfs幸运值为该数的数字的个数。这算是状态压缩么……
问题2也迎刃而解:枚举第一个数字的幸运值,然后dfs其余6个数字幸运值之和,在爆搜过程中处理组合方案数。
问题3:数学基础。。。。。。数死早飘过。
计算n个数的组合,用dfs最容易。完成一件事情,需要若干步骤,每一步的完成方式相乘,就是组合方案数。乘法原理。dfs的魅力可见一斑。
代码如下:
/*
ID: j.sure.1
PROG:
LANG: C++
*/
/****************************************/
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <stack>
#include <queue>
#include <vector>
#include <map>
#include <string>
#include <iostream>
#define INF 0x3f3f3f3f
#define LL long long
using namespace std;
/****************************************/
const int mod = 1e9 + 7;
LL dp[15][15], qty[15], ans;
int num[15], cnt;

void Comb(int other, int id, int mine, LL cur)
{
	if(other >= mine) return ;//其他党派幸运值超过或等于小象幸运值
	if(id == 7) {//其他六个党派分配完毕
		if(mine > other) {
			ans += cur; ans %= mod;
			return ;
		}
		return ;
	}
	//乘法原理
	for(int i = 0; i < mine; i++) {//爆搜,下一个党派分配一个数字
		if(qty[i]) {
			qty[i]--;//分配出去的数字不能再用
			Comb(other+i, id+1, mine, cur*(qty[i]+1)%mod);//根据乘法原理,方案数 = 每个步骤的方式相乘
			qty[i]++;
		}
	}
}

LL dfs(int len, int lucky, bool bnd)
{
	LL &f = dp[len][lucky];
	if(len == 0) {
		if(!lucky) return f = 1;
		return 0;
	}
	if(!bnd && (~f)) return f;
	int lim = bnd ? num[len] : 9;
	LL ret = 0;
	for(int k = lim; k >= 0; k--) {
		ret += dfs(len-1, lucky-(k==4||k==7), bnd && k==lim);
	}
	if(!bnd) f = ret;
	return ret;
}

void Solve(int x)
{
	cnt = 0;
	ans = 0;
	while(x) {
		num[++cnt] = x % 10;
		x /= 10;
	}
	for(int i = 0; i <= cnt; i++) {
		qty[i] = dfs(cnt, i, true);//数位DP处理出比n小的所有数当中,幸运值为i的数的个数
	}
	qty[0]--;//去除数字0,没人会得到0
	for(int i = 1; i <= cnt; i++) {
		Comb(0, 1, i, qty[i]);//枚举小象的幸运值,对其他党派进行dfs算出组合方案数
	}
}

int main()
{
#ifdef J_Sure
//	freopen("000.in", "r", stdin);
//	freopen(".out", "w", stdout);
#endif
	int n;
	memset(dp, -1, sizeof(dp));
	scanf("%d", &n);
	Solve(n);
	printf("%lld\n", ans);
	return 0;
}



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值