• [HNOI2009] 有趣的数列


    题目描述

    我们称一个长度为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的值。

    输入输出格式

    输入格式:

    输入文件只包含用空格隔开的两个整数n和P。输入数据保证,50%的数据满足n<=1000,100%的数据满足n<=1000000且P<=1000000000。

    输出格式:

    仅含一个整数,表示不同的长度为2n的有趣的数列个数mod P的值。

    输入输出样例

    输入样例#1: 
    3 10
    输出样例#1: 
    5


    虽然好多人是打表找规律发现答案是卡特兰数的2333,但其实你如果学了杨表就会发现这就是一个2*n的杨表,直接列式子就是 (2n)!/(n+1)!/n!。
    但是模数不是质数怎么办啊QWQ
    一开始想要把P质因数分解然后用二元组表示阶乘最后CRT合并的,而且竟然质因数分解也想写最近新学的Pillard's Rho,这么一算代码至少要5k啊。。。写死算了QWQ
    但是想一想,模数不是质数最多也就是做除法比较麻烦。。。那我们干脆就不做除法了,直接把每个质因子在答案里的次数算出来然后都乘起来不就行了吗QWQ
    因为只需要算三个阶乘,所以上述方法还是贼快并且贼好写的233333

    #include<bits/stdc++.h>
    #define ll long long
    using namespace std;
    const int maxn=2000005;
    
    inline int ksm(int x,int y,const int ha){
    	int an=1;
    	for(;y;y>>=1,x=x*(ll)x%ha) if(y&1) an=an*(ll)x%ha;
    	return an;
    }
    
    int n,p,zs[maxn/10],t=0,ans=1,N;
    bool v[maxn];
    
    inline int solve(int x){
    	int now=0;
    	ll y=x;
    	
    	while(y<=N) now+=N/y-n/y-(n+1)/y,y*=(ll)x; 
    	
    	return ksm(x,now,p);
    }
    
    int main(){
    	scanf("%d%d",&n,&p),N=n<<1;
    	
    	const int ha=p;
    	
    	for(int i=2;i<=N;i++){
    		if(!v[i]) zs[++t]=i,ans=ans*(ll)solve(i)%ha;
    		for(int j=1,u;j<=t&&(u=zs[j]*i)<=N;j++){
    			v[u]=1;
    			if(!(i%zs[j])) break;
    		}
    	}
    	
    	printf("%d
    ",ans);
    	return 0;
    }
    

      

     
  • 相关阅读:
    孤儿进程与僵尸进程
    python with as的用法
    工作目录与os.getcwd()
    内置模块
    迭代器,生成器
    表达式,语句
    字符流
    字节流
    File
    触发器的操作
  • 原文地址:https://www.cnblogs.com/JYYHH/p/9214391.html
Copyright © 2020-2023  润新知