有趣的数列
【题目描述】
我们称一个长度为 2n 的数列是有趣的,当且仅当该数列满足以下三个条件:
(1)它是从
1
到
(2)所有的奇数项满足 a1<a3<…<a2n−1 ,所有的偶数项满足 a2<a4<…<a2n ;
(3)任意相邻的两项 a2i−1 与 a2i ( 1≤i≤n )满足奇数项小于偶数项,即: a2i−1<a2i 。
现在的任务是:对于给定的
n
,请求出有多少个不同的长度为
因为最后的答案可能很大,所以只要求输出答案
mod
P
的值。
【输入描述】
输入文件只包含用空格隔开的两个整数
【输出描述】
仅含一个整数,表示不同的长度为
【样例输入】
3 10
【样例输出】
5
【Solution】
我们将这
好比是两个栈,一个装奇数位的数字,一个装偶数位的数字,然后从小到大扫过每个数,决定它放进哪个栈。
这样,我们就可以满足第一、二个条件了。
第三个条件如何满足呢?
我们发现,装偶数位的数字的栈的元素个数一定要小于或等于装奇数位的数字的栈的元素个数。
为什么呢?因为如果出现违背上面那条原则的情况,那么就会出现:第
2k
个数已经放好了,第
2k+2
个数也已经放好了,而第
2k+1
个数还没有放好(因为放在偶数位上的数字个数比放在奇数位上的数字个数要多)。
而我们是从小到大放的数,所以要放在第
2k+1
上的数一定比第
2k
、
2k+2
个数要大,不符合第三条情况。
如果我们把放在偶数位上视作
y+1
, 放在奇数位上视作
x+1
,那么放
2n
个数就可以转化为在平面上从
(0,0)
走到
(n,n)
。
因为时时刻刻
x>=y
,所以相当于走到
(n,n)
且不可以穿过直线
y=x
的路径总数!
根据我之前写的网格这篇博文,
因为取模的 p 不是素数,所以不能用逆元乱搞了。
我们可以用质因数分解的方法,将答案的唯一分解式算出来。
这里我想到了一个类似分治的方法。
我们可以用筛素数的方法,求出每个数
设唯一分解式的第 i 个质数的指数为
然后就可以 A 了。
【Code】
- #include <iostream>
- #include <cstdio>
- #include <cstring>
- #include <ctime>
- using namespace std;
- #define LL long long
- typedef LL bign;
- LL tt[2000010];
- LL prime[2000010];
- LL first[2000010];
- bool no_prime[2000010];
- LL n,m;
- bign ans=1;
- LL power(LL x,LL y){
- if(y==0)return 1;
- if(y==1)return x%m;
- LL tmp=power(x%m,y/2);
- if(y&1)return tmp*tmp%m*(x%m)%m;
- else return tmp*tmp%m;
- }
- void make1(LL x){
- while(1){
- if(x==1)return;
- if(prime[first[x]]==x){
- tt[first[x]]++;
- return;
- }
- else{
- while(x%prime[first[x]]==0){
- tt[first[x]]++;
- x/=prime[first[x]];
- }
- }
- }
- }
- void make2(LL x){
- while(1){
- if(x==1)return;
- if(prime[first[x]]==x){
- tt[first[x]]–;
- return;
- }
- else{
- while(x%prime[first[x]]==0){
- tt[first[x]]–;
- x/=prime[first[x]];
- }
- }
- }
- }
- void Pyh(){
- if(!(n&1)){
- tt[1]=(2*n-(n+2)+1)/2+1;
- for(LL i=n+3;i<=2*n-1;i+=2)make1(i);
- for(LL i=2;i<=(n+2)/2-1;i++)make2(i);
- for(LL i=1;i<=prime[0];i++)ans=ans*power(prime[i]%m,tt[i])%m;
- printf(”%lld\n”,ans%m);
- }
- else{
- tt[1]=(2*n-(n+3)+1)/2+1;
- for(LL i=n+2;i<=2*n-1;i+=2)make1(i);
- for(LL i=2;i<=(n+1)/2;i++)make2(i);
- for(LL i=1;i<=prime[0];i++)ans=ans*power(prime[i],tt[i])%m;
- printf(”%lld\n”,ans%m);
- }
- }
- int main(){
- scanf(”%lld%lld”,&n,&m);
- for(LL i=2;i<=2*n;i++){
- if(!no_prime[i]){
- prime[++prime[0]]=i;
- first[i]=prime[0];
- }
- LL j=1,t=i*prime[1];
- while(j<=prime[0]&&t<=2*n){
- first[t]=j;
- no_prime[t]=true;
- if(i%prime[j]==0)break;
- t=i*prime[++j];
- }
- }
- Pyh();
- return 0;
- }