題目:https://nanti.jisuanke.com/t/41420c++
題意:給你一個集合,而後讓你拆成兩個集合 x,y 求知足 x>y && x-(x集合中最小值) <=y 的方案數spa
思路:首先咱們先拆分問題,咱們能不能求出集合不一樣值的方案數,這個很簡單,咱們dp[i],i表明當前重量的方案數,而後咱們很容易就能得知枚舉重量 推導式就是 dp[i]=dp[i]+dp[i-a[i]],如今咱們如何求出方案數咱們已經知道了,咱們怎麼獲得知足題目給的條件的方案數呢,咱們知道總共集合和是多少,咱們又知道當前重量是多少 ,咱們只要知道當前集合的最小值x是多少, i>sum-i && (i-x)<= sum-i, 如今問題就在咱們如何肯定最小值,其實很簡單,咱們只要把物品從大到小排序,咱們就能肯定當前放的物品必定是當前最小,而後判斷便可code
#include<bits/stdc++.h> #define maxn 305 #define mod 1000000007 using namespace std; typedef long long ll; int t,n; int a[maxn]; int sum,num; int vis[maxn]; int dp[150005]; void init(){ scanf("%d",&n); memset(dp,0,sizeof(dp)); for(int i=1;i<=n;i++){ scanf("%d",&a[i]); num+=a[i]; } } int pan(int j,int x){ if(j>=num-j&&j-x<=num-j) return 1; return 0; } int cmp(int x,int y){ return x>y; } int main(){ scanf("%d",&t); while(t--){ sum=0;num=0; init(); sort(a+1,a+n+1,cmp); dp[0]=1; for(int i=1;i<=n;i++){ for(int j=num;j>=a[i];j--){ dp[j]=(dp[j]+dp[j-a[i]])%mod; if(pan(j,a[i])){ sum=(sum+dp[j-a[i]])%mod; } } } printf("%d\n",(sum+mod)%mod); } }