题目描述
猜结论
我们猜测如果出现相邻的两个R(注意第一个和最后一个是R也算),那么就一定不合法。同时,一个合法的序列还要能够组成直角多边形。
假设序列有x个L,y个R
90x+270y=180(n-2)且x+y=n
解得x=n/2+2,y=n/2-2
所以n为奇数是GG的,n为偶数时L与R的个数是确定的。
讨论三种情况:
1、第一个是L最后一个是R
2、第一个是R最后一个是L
3、第一个和最后一个都是L
第一、二种都可以考虑放了y个R,然后在R与R中间插入L,每个空至少插一个L,最前面或最后面也是一个空,答案为
2Cy−1x−1
第三种就是多了一个空,答案为
Cyx−1
于是计算即可。
当然,想过要打高精度,而且还应该用FFT加速高精度乘法,这里只提供70分代码
#include<cstdio>
#include<algorithm>
#define fo(i,a,b) for(i=a;i<=b;i++)
using namespace std;
typedef long long ll;
int pri[5000+10],f[5000+10],a[5000+10];
bool bz[5000+10];
int i,j,k,l,t,n,m,x,y,top;
ll ans;
ll C(int n,int m){
if (n<m||m<0) return 0;
int i,k;
fo(i,1,n){
k=i;
while (k>1){
a[f[k]]++;
k/=f[k];
}
}
fo(i,1,m){
k=i;
while (k>1){
a[f[k]]--;
k/=f[k];
}
}
fo(i,1,n-m){
k=i;
while (k>1){
a[f[k]]--;
k/=f[k];
}
}
ll t=1;
fo(i,1,5000)
while (a[i]){
a[i]--;
t=t*i;
}
return t;
}
void prepare(){
fo(i,2,5000){
if (!bz[i]) pri[++top]=i,f[i]=i;
fo(j,1,top){
if (i*pri[j]>5000) break;
bz[i*pri[j]]=1;
if (i%pri[j]==0){
f[i*pri[j]]=f[i];
break;
}
f[i*pri[j]]=pri[j];
}
}
}
int main(){
scanf("%d",&n);
if (n%2==1) printf("0\n");
else{
prepare();
x=(n+4)/2;
y=n-x;
ans=2*C(x-1,y-1)+C(x-1,y);
printf("%lld\n",ans);
}
}