LightOJ 1193 Dice (II)(前綴和優化dp)

1193 - Dice (II)
Time Limit: 3 second(s) Memory Limit: 32 MB

You have N dices; each of them has K faces numbered from 1 to K. Now you can arrange the N dices in a line. If the summation of the top faces of the dices is S, you calculate the score as the multiplication of all the top faces.

Now you are given N, K, S; you have to calculate the summation of all the scores.

Input

Input starts with an integer T (≤ 25), denoting the number of test cases.

Each case contains three integers: N (1 ≤ N ≤ 1000) K (1 ≤ K ≤ 1000) S (0 ≤ S ≤ 15000).

Output

For each case print the case number and the result modulo 100000007.

Sample Input

Output for Sample Input

5

1 6 3

2 9 8

500 6 1000

800 800 10000

2 100 10

Case 1: 3

Case 2: 84

Case 3: 74335590

Case 4: 33274428

Case 5: 165



題意:有n枚有順序的色子,有k面,若色子的點數和爲s,求其乘積,最後求所有點數和爲s的乘積的和
題解:該題爲dp,網上其他題解都寫得好複雜。。。但是我推出來爲毛就那麼簡單
和其他題解的一樣,先設dp【i】【j】爲前i個色子的點數和爲j的所有乘積和
        那麼就有,dp【i】【j】=∑dp【i-1】【j-l】*l,其中l∈【1,k】
                    即,dp【i】【j】=                                     dp【i-1】【j-1】*1+dp【i-1】【j-2】*2+……+dp【i-1】【j-k+1】*(k-1)+dp【i-1】【j-k】*k
 將j換成j+1有,dp【i】【j+1】=dp【i-1】【j】*1+dp【i-1】【j-1】*2+dp【i-1】【j-2】*3+……+dp【i-1】【j-k+1】*k
那麼就有遞推,dp【i】【j+1】=dp【i】【j】+dp【i-1】【j】+……+dp【i-1】【j-k+1】-dp【i-1】【j-k】*k
若設sum【j】=dp【i-1】【1】+dp【i-1】【2】+……+dp【i-1】【j】
那麼遞推轉移公式改寫成,dp【i】【j+1】=dp【i】【j】+sum【j】-sum【j-k】-dp【i-1】【j-k】*k
需要注意的是,上式2個減去的部分需要判斷j-k是否大於0,若否則不需要減
那麼現在已經可以在O(1)時間內轉移了,所以時間複雜度爲O(n*s)
另外,由於內存不夠,而且當前dp值只與上一行的dp值有關,所以數組用滾動的就行了

#include<stdio.h>
#include<string.h>
#define mod 100000007
long long dp[2][15008];
long long sum[15008];
int main()
{
    int t,n,k,s,i,j,now,cas=1;

    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d%d",&n,&k,&s);
        memset(dp,0,sizeof(dp));
        for(i=1;i<=k;i++) dp[1][i]=i;
        for(i=2; i<=n; i++)
        {
            now=i&1;
            memset(sum,0,sizeof(sum));
            for(j=1; j<=s; j++)
            {
                sum[j]=(sum[j-1]+dp[now^1][j])%mod;
                dp[now][j]=(dp[now][j-1]+sum[j-1])%mod;
                if(j>k) dp[now][j]=((dp[now][j]-sum[j-k-1]-dp[now^1][j-k-1]*k)%mod+mod)%mod;
            }
        }
        printf("Case %d: %lld\n",cas++,dp[n&1][s]);
    }

    return 0;
}


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