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