多边形序列70分

题目描述

这里写图片描述

猜结论

我们猜测如果出现相邻的两个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,最前面或最后面也是一个空,答案为 2Cy1x1
第三种就是多了一个空,答案为 Cyx1
于是计算即可。
当然,想过要打高精度,而且还应该用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);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值