解法一: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;
}