题意:
你有一个容量为2*n的背包,现在有n种食物,第i种事物的体积为i,数目为ai个。还有m种武器,每种武器体积为bi。
现在要求背包里装一个武器,任意食物的方案数。
思路:
官方给的就很详细了Orz......
不懂五边形数定理的同学可以看维基的介绍:五边形数定理 、分割数
代码:
#include<bits/stdc++.h>
const int N = 1e5+10;
const int mod = 1e9+7;
using namespace std;
int n=1e5,m,l;
int arr[N],dp[N],tmp[N];
void init(){
arr[0] = 1;
for(int i=1,j=1;i<=1000;i++){
tmp[i] = j * ( 3 * j - 1 ) / 2;
if(j>0)j=-j;
else j=-j+1;
}
for(int i=1;i<=n;i++){
for(int j=1,k=1;i>=tmp[j];j++,k++){
if(k==5)k-=4;
arr[i] += (k<=2?1:-1) * arr[i-tmp[j]];
if(arr[i]>=mod)arr[i]-=mod;
else if(arr[i]<0)arr[i]+=mod;
}
}
}
int main()
{
init();
int cas = 0 , x ;
while(scanf("%d%d",&n,&m)==2){ l = n<<1;
for(int i=0;i<=l;i++)dp[i] = arr[i];
for(int i=1;i<=n;i++){
scanf("%d",&x);
long long t = 1LL * (x+1) * i;
if(t<=l){
for(int j=l;j>=t;j--){
dp[j] -= dp[j-t];
if(dp[j]<0)dp[j]+=mod;
}
}
}
for(int i=1,j=n+1,sum=dp[0];i<=n;sum+=dp[i++],j++){
if(sum>=mod)sum-=mod;
dp[j] -= sum;
if(dp[j]<0)dp[j]+=mod;
}int ans = 0;
while(m--){
scanf("%d",&x);
ans += dp[l-x];
if(ans>=mod)ans-=mod;
}printf("Case #%d: %d\n",++cas,ans);
}return 0;
}