題意:
你有一個容量爲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;
}