标签:应该 inline continue void bre rod n+1 a* i++
问题:
我们称一个长度为\(2n\)的数列是有趣的,当且仅当该数列满足以下三个条件:
(1)它是从\(1\)到\(2n\)共\(2n\)个整数的一个排列{\(Ai\)};
(2)所有的奇数项满足\(A1<A3<…<A2n-1\),所有的偶数项满足\(A2<A4<…<A2n\);
(3)任意相邻的两项\(A2i-1\)与\(A2i(1≤i≤n)\)满足奇数项小于偶数项,即:\(A2i-1<A2i\)。
现在的任务是:对于给定的\(n\),请求出有多少个不同的长度为\(2n\)的有趣的数列。因为最后的答案可能很大,所以只要求输出答案\(mod P\)的值。
解:
$1 2 5 14 42 $
奇数小于偶数 \(入栈>=出栈\) 这是一个卡特兰数
我们应该用 一下公式求解
$ \frac {c_{2n}^n}{n+1}$ =\(\frac {2n!} {n!*n!}\)*\(\frac {1} {n+1}\)=\(\prod_{n+2}^{2**n}\)
但是这道题还是没有完
你会发现它模数不一定是质数 所以你要用扩展lucas
好吧其实是唯一分解定理来进行约分
虽然我不知道为什么 可以约分
开先我对于每个质因数筛次数 \(T 50\)
经过hyh 的指点
我才发现 可以从后往前讨论 对每个数进行分解 \(sqrt\)级别
code:
#include<stdio.h>
#include<iostream>
using namespace std;
#define maxnn 2000100
#define ll long long
ll zhi[maxnn];
ll n,p;
ll phi[maxnn];
ll cnt[maxnn];
ll len=0;
ll is[maxnn];
void init()
{
phi[1]=1;
for(ll i=2;i<=2000000;i++)
{
if(!phi[i])
zhi[++len]=i;
for(int j=1;j<=len&&zhi[j]*i<=2000000;j++)
{
phi[zhi[j]*i]=1;
if(i%zhi[j]==0) break;
}
}
}
void iiit(){
for(ll i=2*n;i>=1;i--)
{
if(is[i])
{
if(zhi[lower_bound(zhi+1,zhi+len+1,i)-zhi]==i) continue;
for(int j=2;j*j<=i;j++)
{
if(i%j==0)
{
is[j]+=is[i];
is[i/j]+=is[i];
break;
}
}
}
}
for(int i=1;i<=len&&zhi[i]<=2*n;i++)
{
if(is[zhi[i]]) cnt[zhi[i]]+=is[zhi[i]];
}
}
ll ksm(ll a,ll b)
{
ll ans=1;
while(b)
{
if(b&1) ans=ans*a%p;
a=a*a%p;
b>>=1;
}
return ans;
}
int main(){
cin>>n>>p;
for(ll i=n+2;i<=2*n;i++) is[i]=1;
for(ll i=1;i<=n;i++) is[i]=-1;
init();
iiit();
ll tot=1;
for(ll i=1;i<=len&&zhi[i]<=2*n;i++)
{
if(cnt[zhi[i]]) tot=tot*ksm(zhi[i],cnt[zhi[i]])%p;
}
cout<<tot%p;
}
标签:应该 inline continue void bre rod n+1 a* i++
原文地址:https://www.cnblogs.com/OIEREDSION/p/11495105.html