Luo Valley P2602 [ZJOI2010] digital count (the number of bits dp)

Digital counting

Topic Portal

Problem-solving ideas

With \ (dp [i] [j ] [k] \) to indicate the length \ (I \) and with \ (J \) is a number in the beginning of the \ (K \) number of occurrences.

The transfer equation is: \ (DP [I] [J] [K] + = \ sum_ ^ {T} = {0}. 9 DP [I -. 1] [T] [K] \) , i.e., the number of each placed in front of a \ (J \) , but in front of this for \ (J \) we have not yet into the calculation, it is: \ (DP [I] [J] [J] + = {I-10 ^. 1 } \) . Note that at this time is calculated with leading 0's.

Then see the code (in fact, do not know how to describe).

code show as below

#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;

inline ll fpow(ll x, ll p){
    ll ans = 1;
    for(; p; p >>= 1, x = 1LL * x * x)if(p & 1)ans = 1LL * x * ans;
    return ans;
}

ll dp[20][15][15];

void work(ll x, ll ans[])
{
    ll num[15];
    ll t = x;
    int cnt = 0;
    while(t){  //把每一位拆出来
        num[++cnt] = t % 10;
        t /= 10;
    }
    for(int i = 1; i < cnt; i ++)  //小于cnt的位数全加上
        for(int j = 1; j <= 9; j ++)
            for(int k = 0; k <= 9; k ++)
                ans[k] += dp[i][j][k];
    for(int j = 1; j < num[cnt]; j ++) //相同位数小于最高位的全加上
        for(int k = 0; k <= 9; k ++)
            ans[k] += dp[cnt][j][k];
    for(int i = cnt - 1; i >= 1; i --){ //遍历每一位
        for(int j = 0; j < num[i]; j ++) //小于这位上数字的全加上
            for(int k = 0; k <= 9; k ++)
                ans[k] += dp[i][j][k];
        for(int u = cnt; u > i; u --) //前面这几位都相等,出现了相同的次数
            ans[num[u]] += num[i] * fpow(10LL, i - 1);
    }
}

int main()
{
    ll a, b;
    scanf("%lld%lld", &a, &b);
    for(int i = 1; i <= 12; i ++){
        for(int j = 0; j <= 9; j ++){
            for(int k = 0; k <= 9; k ++)
                for(int t = 0; t <= 9; t ++)
                    dp[i][j][k] += dp[i - 1][t][k];
            dp[i][j][j] += fpow(10LL, i - 1);
        }
    }
    ll ans1[15] = {0};
    ll ans2[15] = {0};
    work(b + 1, ans1);
    work(a, ans2);
    for(int i = 0; i <= 9; i ++)
        printf("%lld ", ans1[i] - ans2[i]);
    return 0;
}

Guess you like

Origin www.cnblogs.com/whisperlzw/p/11404057.html