题意:有n个石头,每个石头重量为a[i],将这n个石头分为2堆,要求第一堆石子比第二堆大,第一堆去掉重量最小的那个石子后又比第二堆小
思路:退背包,先用01背包算出容量为j的方案数,然后再从小到大到顺序使石子推出背包
代码:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
const int maxn=3e2+9;
const int mod=1e9+7;
int a[maxn];
ll dp[maxn*500],f[maxn*500];
int main(){
int i,j,k,n,t;
cin>>t;
while(t--){
cin>>n;
int sum=0;
for(i=0;i<n;i++){
cin>>a[i];
sum+=a[i];
}
sort(a,a+n);
memset(dp,0,sizeof(dp));
dp[0]=1;
for(i=0;i<n;i++){
for(j=sum;j>=a[i];j--)dp[j]=(dp[j]+dp[j-a[i]])%mod;
}
ll ans=0;
for(i=0;i<n;i++){
int l=(sum+1)/2,r=(sum+a[i])/2;
for(j=a[i];j<=sum;j++){
f[j]=dp[j-a[i]];
dp[j]=(dp[j]-dp[j-a[i]]+mod)%mod;
}
for(j=max(l,a[i]);j<=r;j++)ans=(ans+f[j])%mod;
}
cout<<ans<<endl;
}
}