這個題是經典0-1揹包問題的變形,在正整數區間[1,n]內,選擇一個子集,和爲n*(n+1)/4,求總共能夠選擇的子集數除以2。首先想到的是窮舉可能的狀況,可是始終超時。後來採用動態規劃,用ans[i][j]表示在區間[0,i]選擇一個其和爲j的子集,總共可能的子集數,因而狀態轉移方程:ios
if(j<i) ans[i][j]=ans[i-1][j];
if(j==i) ans[i][j]=ans[i-1][j]+1;
if(j>i) ans[i][j]=ans[i-1][j]+ans[i-1][j-i]; spa
其中起始點a[1][1]=1,i取值範圍:1~n,j取值範圍:1~n*(n+1)/4。code
/* ID:jzzlee1 PROG:subset LANG:C++ Dear double_tings: i love you. */ //#include<iostream> #include<fstream> #include<cmath> #include<string> #include<cstring> #include<bitset> using namespace std; ifstream cin("subset.in"); ofstream cout("subset.out"); long long ans[40][40*(40+1)/2]; int main(){ int n; cin>>n; int half=n*(n+1)/4; if(n*(n+1)%4!=0) { cout<<0<<endl; return 0; } ans[1][1] = 1; for(int i = 2; i <= n; i++) for(int j = 1; j <= half; j++) if(j < i) ans[i][j] = ans[i-1][j]; else if(j == i) ans[i][j] = ans[i-1][j]+1; else ans[i][j] = ans[i-1][j] + ans[i-1][j-i]; cout<<ans[n][half]/2<<endl; return 0; }