AtCoder AGC009E Eternal Average (DP)

Topic Link

https://atcoder.jp/contests/agc009/tasks/agc009_e

answer

He has been discouraging. . .
The first step is the conversion apparent: it is equivalent to a start number \ (1 \) with \ (\ frac {n + m -1} {k-1} \) chance to select a number to each time it becomes \ (K \) th original \ (\ FRAC. 1 {{}} K \) , and finally from the (n + m \) \ selected number of \ (m \) a, Q can select how many different number.
Then consider into \ (K \) number of binary decimal, and finally formed is assumed \ (D_1, D_2, ..., D_ {n-m} + \) , then \ (\ sum ^ {n + m} _ { D_i. 1} = = I. 1 \) .
a \ (D \) binary fraction can be expressed as \ (m \) a \ (K \) negative integer powers if and only if the sum of a value of each of does not exceed \ (m \) and and \ (m \) mode \ ((k-1) \ ) congruent. (Apparently)
, but while also ensuring \ (1 \) may be expressed as \ ((n + m) \ ) a \ (K \)Negative integer powers sum, and which contains \ (m \) number. Then it can be converted into \ (1 \) Save This may be expressed as decimal \ (n-\) a \ (K \) of the sum of negative integral powers. (Okay I thought this step out of the autistic ...... ah ......)
So in the end is to calculate the number of sequence \ (a_1, a_2, ..., a_l \ (1 \ le l \ le \ frac {n-+ m-. 1} {K-. 1}) \) , satisfies \ (0 \ le a_i \ le k-1, a_l> 0, \ sum ^ l_ {i = 1} a_i \ le m, \ sum ^ l_ {i = 1} a_i \ equiv m (\ mod k-1), \ sum ^ l_ {i = 1} k-1-a_i \ le n-1, \ sum ^ l_ {i = 1} k-1 -a_i \-n-equiv. 1 (\ K-MOD. 1) \) , directly to dp. Time complexity \ (O ((n-m +) K) \) .

Code

#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<cassert>
#define llong long long
using namespace std;

const int N = 4e3;
const int P = 1e9+7;
llong dp[N+3][N+3],sdp[N+3][N+3];
int n1,n2,m,len;
llong ans;

int main()
{
    scanf("%d%d%d",&n1,&n2,&m); len = (n1+n2-1)/(m-1);
    dp[0][0] = 1ll; for(int j=0; j<=n2; j++) sdp[0][j] = 1;
    for(int i=1; i<=len; i++)
    {
        for(int j=0; j<=n2; j++)
        {
            if(j>=m) {dp[i][j] = (sdp[i-1][j]-sdp[i-1][j-m]+P)%P;}
            else {dp[i][j] = sdp[i-1][j];}
            if((n2-j)%(m-1)==0 && i*(m-1)-j<=n1-1 && (n1-1-i*(m-1)+j)%(m-1)==0) {ans = (ans+dp[i][j]-dp[i-1][j]+P)%P;}
        }
        sdp[i][0] = dp[i][0]; for(int j=1; j<=n2; j++) sdp[i][j] = (sdp[i][j-1]+dp[i][j])%P;
    }
    printf("%lld\n",ans);
    return 0;
}

Guess you like

Origin www.cnblogs.com/suncongbo/p/11519281.html