CF258B

CF258B

質問の意味:

数$ [1、M] $間隔アクセスの数は、4と7の最初の選択された数を求める個人は、スキーム7に個体数の4,7他人の合計よりも大きいです。

ソリューション:

必要な$ M $の入力が大きくなること、およびすべてのビットの貢献を検討する必要があるので、デジタルDPを考慮することができます。
提供$ fは[i] [j]は $ $ I $は$ 4と$ 7の数の$ J $の形態があり、最初のビットであり、その後のDFSラインを使用して転送します。

CODE:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>

using namespace std;

#define LL long long
const LL MOD = 1e9+7;

LL final,dp[16][16],c[16];
int bit[16],l,cnt,tot,m;

int work(int m, int n) {
    cnt = tot = l = 0;
    for (; m; m /= 10) bit[++l] = m % 10;
    for (int i = l; i && tot <= n; --i) {
        for(int j = 0 ; j < bit[i] ; j++)
            if (j == 4 || j == 7) {
                if (tot < n) cnt += dp[i - 1][n - tot - 1];
            } else cnt += dp[i - 1][n - tot];
        if (bit[i] == 4 || bit[i] == 7) ++tot;
    }
    if(tot == n) ++cnt;
    if(n == 0) --cnt;
    return cnt;
}
void dfs(int t, int now, int lim, LL ans) {
    if (t == 6) (final += ans) %= MOD;
    else {
        for (int i = 0; i <= 9 && i + now < lim; ++i)
            if (c[i]) {
                c[i]--;
                dfs(t + 1, now + i, lim, ans * (c[i] + 1) % MOD);
                c[i]++;
            }
    }
}

int main() {
    scanf("%d", &m);
    dp[0][0] = 1;
    for(int i = 0 ; i <= 9 ; i++) {
        for(int j = 0 ; j <= i ; j++) {
            dp[i + 1][j + 1] += dp[i][j] * 2; 
            dp[i + 1][j] += dp[i][j] * 8;
        }
    } 
    for(int i = 0 ; i <= 9 ; i++) c[i] = work(m, i);
    for(int i = 0 ; i <= 9 ; i++) {
            if (c[i]) {
            --c[i];
            dfs(0, 0, i, (c[i] + 1) % MOD);
            ++c[i];
        }
    }
    printf("%lld \n", final);
    //system("pause");
    return 0;
}

おすすめ

転載: www.cnblogs.com/Repulser/p/11373454.html