codeforces 258B

很經典的思路啊,比賽的時候沒怎麼多想,其實還很簡單的。
題意:有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;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章