题目
题目链接:https://ac.nowcoder.com/acm/contest/373/B
lililalala正在玩一种有 N (1<=N<=300)个回合的回合制RPG游戏,初始分数为0,第 i 个回合lililalala有如下两种选择。
A.将分数加上 ai (-666<=ai<=666)
B.将分数 × (-1)
lililalala同样也很讨厌野兽数 666 ,但是他很却喜欢数字 -666。
他想知道有多少种不同的方案使得 N个回合后分数变为 -666 ,且在任何一个回合之后分数都不为 666。
如果两种方案有任何一个回合选择不同,就认为这两种方案是不同的。
答案请对 1e8+7 取模。
题解
dp[2][2*300*666],滚动数组+偏移量,
第二维是背包容量,把-300*666到300*666移动到了0到2*300*666
计一个偏移量off,那么dp[0][0]=1实际上就是dp[0][off]=1,其余操作就是裸背包转移
代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=300*666*2+1;
const int mod=1e8+7;
const int off=300*666;
int n,a[maxn];
ll dp[2][maxn];
int now,last;
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;++i)
scanf("%d",&a[i]);
now=0;last=1;
dp[now][off]=1;
for(int i=1;i<=n;++i)
{
swap(now,last);
for(int j=0;j<maxn;++j)
dp[now][j]=0;
for(int j=0;j<maxn;++j)
{
if(j==off+666)continue;
(dp[now][j]+=dp[last][2*off-j])%=mod;
if(j-a[i]>=0&&j-a[i]<maxn)(dp[now][j]+=dp[last][j-a[i]])%=mod;
}
}
printf("%lld\n",dp[now][off-666]);
return 0;
}