有趣的数列 唯一分解定理+卡特兰数
Posted oieredsion
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了有趣的数列 唯一分解定理+卡特兰数相关的知识,希望对你有一定的参考价值。
问题:
我们称一个长度为\(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^nn+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;
以上是关于有趣的数列 唯一分解定理+卡特兰数的主要内容,如果未能解决你的问题,请参考以下文章