题意:中文题面。
思路:观察规律,相同得‘+’,不同得‘-’,跟异或运算很相似,可用0代表‘+’,1代表‘-’。第一层有n位,n不大于24,因此可用n位二进制数来表示当前一层的状态,数位上的0和1分别代表相应的符号,求下一层的状态时只需要当前层的各位数字两两异或即可组成下一层的状态,每向下一层,位数就减一。
由于n位二进制数共有2的n次方种情况,先求出最大的一种即2^n-1,然后依次-1枚举到0即可。二进制不熟练,还有多重循环,写的时候晕头转向,还好写对了。
打表代码:
#include<bits/stdc++.h>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define INF 0x3f3f3f3f
typedef long long LL;
int ans[25],a[25];//一个记录结果,一个记录中间状态
int main(){
memset(ans,0,sizeof(ans));
for(int i=1;i<=24;++i){//最外层决定顶层位数
a[1]=(1<<i)-1;//最大值
while(a[1]>=0){//从最大值开始往下枚举第一层的状态
for(int j=2;j<=i;++j){//求出下面n-1层的状态
a[j]=0;
for(int k=0;k<(i-j+1);++k){
a[j]|=((((a[j-1]>>k)&1)^((a[j-1]>>(k+1))&1))<<k);
}
}
int cnt1=0,cnt2=0;//计数
for(int j=1;j<=i;++j){//遍历每一层的状态
for(int k=0;k<i-j+1;++k){//统计当前层
if((a[j]>>k)&1)++cnt1;
else ++cnt2;
}
}
if(cnt1==cnt2)++ans[i];
--a[1];
}
}
for(int i=1;i<25;++i)
printf("%d\n",ans[i]);
}
#include<bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
typedef long long LL;
int main(){
int n,ans[25]={0,0,0,4,6,0,0,12,40,0,0,171,410,0,0,1896,5160,0,0,32757,59984,0,0,431095,822229};
while(scanf("%d",&n),n){
printf("%d %d\n",n,ans[n]);
}
}