您的位置:首页 > 其它

codeforces 258B

2016-01-22 23:29 337 查看
很经典的思路啊,比赛的时候没怎么多想,其实还很简单的。

题意:有7个party,然后有m个数字,1-m,每个party可以选择其中一个数字,4和7是幸运的字符,每个数字有多个幸运字符比如4447有四个。

问你第一个party选的数字的幸运字符个数 严格大于其他party选择的数字的幸运字符个数的和 的选择方法数。

用数位dp预处理出1-m之间幸运字符个数为i数字数为c[i],然后枚举第一个party选择的i,然后深搜其他party,在满足条件的情况下,全排列即可,最后求个和

//
//  Created by Matrix on 2016-01-22
//  Copyright (c) 2015 Matrix. All rights reserved.
//
//
//#pragma comment(linker, "/STACK:102400000,102400000")
#include <algorithm>
#include <cctype>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <string>
#include <sstream>
#include <set>
#include <vector>
#include <stack>
#define ALL(x) x.begin(), x.end()
#define INS(x) inserter(x, x,begin())
#define ll long long
#define CLR(x) memset(x, 0, sizeof x)
using namespace std;
const int inf = 0x3f3f3f3f;
const int MOD = 1e9 + 7;
const int maxn = 1e6 + 10;
const int maxv = 1e3 + 10;
const double eps = 1e-9;

ll pow_mod(ll a, ll n) {
ll ret = 1;
while(n) {
if(n & 1) ret = ret * a % MOD;
a = a * a % MOD;
n >>= 1;
}
return ret;
}
int digit[55];
ll c[10];
ll dp[55][20][20];
ll dfs(int step, int limit, int cnt, int ju) {
if(step == 0) {
return cnt == ju;
}
if(!limit && dp[step][cnt][ju] != -1) return dp[step][cnt][ju];
ll ret = 0;
int up = limit ? digit[step] : 9;
for(int i = 0; i <= up; i++) {
ret += dfs(step-1, limit && i == up, cnt + (i == 4 || i == 7 ? 1 : 0), ju);
}
if(!limit) dp[step][cnt][ju] = ret;
return ret;
}
ll A(ll n, ll a) {
ll ret = 1;
if(a > n) return 0;
while(a--) {
ret = ret * n % MOD;
n--;
}
return ret;
}
ll calc(ll n, int ju) {
memset(dp, -1, sizeof dp);
int top = 0;
while(n) {
digit[++top] = n % 10;
n /= 10;
}
return dfs(top, 1, 0, ju);
}
ll res;
void DFS(int step, int sum, int ju) {
if(step == 6) {
ll cnt = 1;
for(int i = 0; i < ju; i++) {
if(digit[i]) {
cnt = cnt * A(c[i], digit[i]) % MOD;
}
}
//      printf("ju = %d  cnt = %lld\n", ju, cnt);
res += cnt;
return;
}
for(int i = 0; i + sum < ju; i++) {
if(digit[i] >= c[i]) continue;
digit[i]++;
DFS(step+1, sum + i, ju);
digit[i]--;
}
}
int main() {
#ifdef LOCAL
freopen("in.txt", "r", stdin);
//  freopen("out.txt","w",stdout);
#endif
ll m;
while(cin >> m) {
CLR(c);
for(int i = 0; i <= 9; i++) {
c[i] = calc(m, i);
}
c[0]--;
//      for(int i = 0; i <= 9; i++) {
//          printf("c[%d] = %lld\n", i, c[i]);
//      }
ll ans = 0;
for(int i = 1; i <= 9; i++) {
if(!c[i]) continue;
res = 0;
CLR(digit);
DFS(0, 0, i);
ans = (ans + res * c[i] % MOD) % MOD;
}
printf("%lld\n", ans);
}

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  dp