lightoj - 1193 - Dice (II) dp / 背包

来源:互联网 发布:淘宝刷手p图软件哪个好 编辑:程序博客网 时间:2024/05/16 19:15

题意:有n个骰子,每个骰子有k面,每个面的权值从1到k,求所有骰子和为s时,他们权值乘积的和。

题解:设dp[i][j]表示到第i个骰子时和为j的乘积和,易写出dp[i][j] = sum{dp[i][j - m] * m, m从1到k,但是这样的dp方程是n * k * s的,所以要优化。类似完全背包的优化,写出dp[i][j-1]的方程,两式做差,得dp[i][j] = dp[i][j-1] + pre[j-1] - pre[j-k-1] - dp[i-1][j-k-1] * k,利用滚动数组优化空间即可。

注意边界的特殊情况。

#include <bits/stdc++.h>//#pragma comment(linker, "/STACK:1024000000,1024000000")using namespace std;#define ll long long#define SZ(x) ((int)(x).size()) #define ALL(v) (v).begin(), (v).end()#define foreach(i, v) for (__typeof((v).begin()) i = (v).begin(); i != (v).end(); ++ i)#define reveach(i, v) for (__typeof((v).rbegin()) i = (v).rbegin(); i != (v).rend(); ++ i) #define REP(i,a,n) for ( int i=a; i<int(n); i++ )#define FOR(i,a,n) for ( int i=n-1; i>= int(a);i-- )#define lson rt<<1, L, m#define rson rt<<1|1, m, Rtypedef pair<int, int> pii;typedef pair<ll, ll> pll;#define mp(x, y) make_pair(x, y)#define pb(x) push_back(x)#define fi first#define se second#define CLR(a, b) memset(a, b, sizeof(a))#define Min(a, b) a = min(a, b)#define Max(a, b) a = max(a, b)const int maxn = 1.5e4 + 7;const int mod = 100000007;int T;int kase;int n, k, s;ll dp[2][maxn];ll pre[maxn];ll solve(){    CLR(dp, 0);    REP(j, 1, k + 1) dp[0][j] = j;    REP(i, 1, n){        int p = i & 1;        pre[i-1] = 0;        REP(j, i, s + 1) pre[j] = (pre[j-1] + dp[!p][j]) % mod;        CLR(dp[p], 0);        dp[p][i+1] = dp[!p][i];        REP(j, i + 2, i + k + 1){            dp[p][j] = ((dp[p][j-1] + pre[j-1] - pre[i-1]) % mod + mod) % mod;        }        REP(j, i + k + 1, s + 1){            dp[p][j] = ((dp[p][j-1] + pre[j-1] - pre[j-k-1] - dp[!p][j-k-1] * k) % mod + mod) % mod;        }    }    //REP(i, 0, n) REP(j, 1, s + 1) printf("%d %d %lld\n", i, j, dp[i&1][j]);    return dp[(n-1)&1][s];}int main(){#ifdef ac    freopen("in.txt","r",stdin);#endif    //freopen("out.txt","w",stdout);    scanf("%d", &T);    while(T--){        scanf("%d%d%d", &n, &k, &s);        printf("Case %d: %lld\n", ++kase, solve());    }    return 0;}


0 0
原创粉丝点击