[BZOJ1485] 有趣的数列 (卡特兰数)

首先要明确这是卡特兰数,证明如下:

我们可以把奇数项和偶数项看成2个数列,然后从1到2*n扫一边可以往2个数列里塞,但必须满足奇数项的个数时刻大于等于偶数项个数(小的话就不能让奇数项小于偶数项了),于是便巧妙地出栈顺序问题吗即卡特兰数。


 

看到p不一定是素数,便想到了exlucas,打完交上去TLE80,这时才看见数据范围是:

n<=1e6,p<=1e9!f**k!

这么大的模数exface啊?(exskyh)

在无奈之中颓了Deepinc的题解发现质因数分解可以线筛+递归处理,学到了学到了。。。


 

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<string>
#include<cstdlib>
#include<vector>
#define int long long 
using namespace std;
const int N=2e6+10;
int ans=1,cnt,n,p,a[N],prime[N],mark[N],f[N];
void init(int x,int y)
{
        if(x==1) return;
        a[f[x]]+=y;
        init(x/f[x],y);
}
int poww(int x,int y,int z)
{
        int sum=1;
        while(y)
        {
                if(y&1) sum=(sum*x)%z;
                y>>=1;
                x=(x*x)%z;
        }
        return sum;
}
main()
{
        //freopen("1.in","r",stdin);
        scanf("%lld%lld",&n,&p);
        for(int i=2;i<=n*2;i++)
        {
                if(!mark[i])
                {
                        prime[++cnt]=i;
                        f[i]=i;
                }
                for(int j=1;j<=cnt;j++)
                {
                        if(i*prime[j]>n*2) break;
                        f[i*prime[j]]=prime[j];
                        mark[i*prime[j]]=1;
                        if(i%prime[j]==0) break;
                }
        }
        for(int i=n+2;i<=n*2;i++) init(i,1);
        for(int i=2;i<=n;i++) init(i,-1);
        for(int i=2;i<=n*2;i++) ans=ans*poww(i,a[i],p)%p;
        printf("%lld",ans);
        return 0;
}

 

转载于:https://www.cnblogs.com/AthosD/articles/11221877.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值