zoukankan      html  css  js  c++  java
  • [HNOI2009]有趣的数列

    题目:洛谷P3200、BZOJ1485、codevs2337。

    题目大意:
    我们称一个长度为$2n$的数列是有趣的,当且仅当该数列满足以下三个条件:
    1. 它是从$1$到$2n$共$2n$个整数的一个排列${a_i}$;
    2. 所有的奇数项满足$a_1<a_3<dots<a_{2n-1}$,所有的偶数项满足$a_2<a_4<dots<a_{2n}$;
    3. 任意相邻的两项$a{2i-1}$与$a_{2i}(1leqslant ileqslant n)$满足奇数项小于偶数项,即:$a{2i-1}<a{2i}$。
    现在的任务是:对于给定的$n$,请求出有多少个不同的长度为$2n$的有趣的数列。因为最后的答案可能很大,所以只要求输出答案$mod P$的值。
    解题思路:
    找找规律,发现,答案是卡特兰数。
    然而$P$并不一定是质数。
    所以用另一个公式:$f_n =frac{C^n_{2n}}{n+1}=(2n)!div (n+1)!div n!$。
    并且$f_i$保证是一个整数。
    由于我们可以很快地求出$n!$内包含某个质数因子的数量(除一下就行了),所以,我们先求出$2n$以内的质数,然后套公式,统计每个质数因子包含的个数,然后快速幂加到答案里即可。
    筛质数用线性筛即可。
    时间复杂度$O(nlog n)$。

    C++ Code:

    #include<bits/stdc++.h>
    #define LoveLive long long
    int prm[1000005];
    bool isnprm[2000005];
    int n,md,cnt=0;
    inline LoveLive pow(LoveLive a,int p){
    	a%=md;
    	LoveLive ans=1;
    	while(p){
    		if(p&1)ans=ans*a%md;
    		a=a*a%md;
    		p>>=1;
    	}
    	return ans;
    }
    int main(){
    	scanf("%d%d",&n,&md);
    	int N=n<<1;
    	for(int i=2;i<=N;++i){
    		if(!isnprm[i])prm[++cnt]=i;
    		for(int j=1;j<=cnt&&prm[j]*i<=N;++j){
    			isnprm[prm[j]*i]=1;
    			if(i%prm[j]==0)break;
    		}
    	}
    	LoveLive ans=1;
    	for(int i=1,m;i<=cnt;++i){
    		int s=0;
    		for(m=N;m/=prm[i];)s+=m;
    		for(m=n;m/=prm[i];)s-=m;
    		for(m=n+1;m/=prm[i];)s-=m;
    		ans=ans*pow(prm[i],s)%md;
    	}
    	printf("%lld
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    兼容ie8 rgba()用法
    WebUploader在display:none 无法运行
    text-overflow: ellipsis 在IE8中不能显示省略号的问题
    关于 href="javascript:;" 在IE8中的问题
    html中select的onchange打开方式
    angularJS 报错总结
    c:if的用法
    layui的编辑器 layedit的异步赋值问题
    Bootstrap- Modal对话框如何在关闭时触发事件
    Spring源码导入IDEA
  • 原文地址:https://www.cnblogs.com/Mrsrz/p/9041689.html
Copyright © 2011-2022 走看看