CodeForces 258B Little Elephant and Elections 数位DP

前面先用数位DP预处理,然后暴力计算组合方式即可。

#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <climits>
#include <string>
#include <iostream>
#include <map>
#include <cstdlib>
#include <list>
#include <set>
#include <queue>
#include <stack>

using namespace std;

typedef long long LL;
const int maxn = 20;
const LL MOD = 1e9 + 7;
int M,lim[maxn],len;
bool vis[maxn][maxn];
struct EE {
    LL cnt[maxn];
    EE() {
        memset(cnt,0,sizeof(cnt));
    }
};
EE f[maxn][maxn], ans;

void getlim(int num) {
    len = 0;
    memset(lim,0,sizeof(lim));
    while(num) {
        lim[len++] = num % 10;
        num /= 10;
    }
}

EE dfs(int now,int cnt,int bound) {
    if(now == 0) {
        EE ret;
        ret.cnt[cnt] = 1;
        return ret;
    }
    if(!bound && vis[now][cnt]) return f[now][cnt];
    int m = bound ? lim[now - 1] : 9;
    EE ret;
    for(int i = 0;i <= m;i++) {
        EE nret = dfs(now - 1,cnt + (i == 4 || i == 7),bound && i == m);
        for(int i = 0;i <= len;i++) ret.cnt[i] += nret.cnt[i];
    }
    if(!bound) {
        f[now][cnt] = ret;
        vis[now][cnt] = true;
    }
    return ret;
}

LL A(LL m,LL n) {
    LL ret = 1;
    for(int i = 1;i <= n;i++) {
        ret *= m; m--; ret %= MOD;
    }
    return ret;
}

LL rest[maxn],rcnt[maxn];
LL dfs1(int now,int sum,int limm) {
    if(sum >= limm) return 0;
    if(now == 7) {
        LL ret = 1;
        for(int i = 0;i < limm;i++) if(rcnt[i]) {
            ret = (ret * A(ans.cnt[i],rcnt[i])) % MOD;
        }
        return ret;
    }
    LL ret = 0;
    for(int i = 0;i < limm;i++) if(rest[i]) {
        rcnt[i]++; rest[i]--;
        ret = (ret + dfs1(now + 1,sum + i,limm)) % MOD;
        rcnt[i]--; rest[i]++;
    }
    return ret;
}

void solve() {
    memset(vis,0,sizeof(vis));
    getlim(M);
    ans = dfs(len,0,1);
    ans.cnt[0]--;
    LL out = 0;
    for(int i = 1;i <= len;i++) if(ans.cnt[i]) {
        memcpy(rest,ans.cnt,sizeof(rest));
        memset(rcnt,0,sizeof(rcnt));
        out = (dfs1(1,0,i) * ans.cnt[i] % MOD + out) % MOD;
    }
    cout << out << endl;
}


int main() {
    cin >> M;
    solve();
    return 0;
}

  

posted @ 2014-08-03 18:52  acm_roll  阅读(271)  评论(0编辑  收藏  举报