1365. 子集的和
解法一:01背包
\(1 \sim n\)的总和\(sum=\frac{n(n+1)}{2}\),若将整数集合\(1 \sim n\)划分成两个和相等的子集,则子集的和\(sum'=\frac{n(n+1)}{4}\)。
问题转化为\(1 \sim n\)中选出若干个数,总和为\(sum'\)的方案数。
const int N = 400;
LL f[N];
int n;
int main()
{
cin>>n;
int sum=n*(n+1)/2;
if(sum % 2) puts("0");
else
{
sum /= 2;
f[0]=1;
for(int i=1;i<=n;i++)
for(int j=sum;j>=i;j--)
f[j]+=f[j-i];
cout<<f[sum]/2<<endl;
}
//system("pause");
return 0;
}
解法二:折半搜索
\(fl[i]\)和\(fr[i]\)分别表示前\(\frac{n}{2}\)个数能凑出的和为\(i\)的个数、后\(\frac{n}{2}\)个数能凑出的和为\(i\)的个数和。
const int N=600;
int fl[N],fr[N];
int n;
void dfs(int l,int r,int sum,int *f)
{
if(l > r)
{
f[sum]++;
return;
}
dfs(l+1,r,sum+l,f);
dfs(l+1,r,sum,f);
}
int main()
{
cin>>n;
int sum=n*(n+1)/2;
if(sum & 1) puts("0");
else
{
sum /= 2;
dfs(1,n/2,0,fl);
dfs(n/2+1,n,0,fr);
LL ans=0;
for(int i=0;i<=sum;i++)
ans+=fl[i]*fr[sum-i];
cout<<ans/2<<endl;
}
//system("pause");
return 0;
}