有趣的数列 [Codevs 2337,Bzoj 1485,HNOI2009]

原创 2016年05月31日 14:03:04

题目地址请点击——


有趣的数列


【题目描述】

我们称一个长度为 2n的数列是有趣的,当且仅当该数列满足以下三个条件:

(1)它是从 12n2n 个整数的一个排列 {ai}

(2)所有的奇数项满足 a1<a3<<a2n1,所有的偶数项满足a2<a4<<a2n

(3)任意相邻的两项 a2i1a2i (1in)满足奇数项小于偶数项,即:a2i1<a2i

现在的任务是:对于给定的 n,请求出有多少个不同的长度为 2n 的有趣的数列。
因为最后的答案可能很大,所以只要求输出答案 mod P 的值。


【输入描述】

输入文件只包含用空格隔开的两个整数 nP


【输出描述】

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


【样例输入】

3 10


【样例输出】

5


【Solution】

我们将这 2n 个数从小到大排个序,然后从小到大决定每一个数放在奇数位还是偶数位。
好比是两个栈,一个装奇数位的数字,一个装偶数位的数字,然后从小到大扫过每个数,决定它放进哪个栈。
这样,我们就可以满足第一、二个条件了。
第三个条件如何满足呢?
我们发现,装偶数位的数字的栈的元素个数一定要小于或等于装奇数位的数字的栈的元素个数。
为什么呢?因为如果出现违背上面那条原则的情况,那么就会出现:第 2k 个数已经放好了,第 2k+2 个数也已经放好了,而第 2k+1 个数还没有放好(因为放在偶数位上的数字个数比放在奇数位上的数字个数要多)。
而我们是从小到大放的数,所以要放在第 2k+1 上的数一定比第 2k2k+2 个数要大,不符合第三条情况。
如果我们把放在偶数位上视作 y+1, 放在奇数位上视作 x+1,那么放 2n 个数就可以转化为在平面上从 (0,0) 走到 (n,n)
因为时时刻刻 x>=y,所以相当于走到 (n,n) 且不可以穿过直线 y=x 的路径总数!
根据我之前写的网格这篇博文,

ans=[Cn2nCn12n] mod p=[(2n)!n!n!(2n)!(n+1)!(n1)!] mod p=[(2n)!(n+1)(2n)!n(n+1)!n!] mod p=(2n)!(n+1)!n! mod p=(2n)(2n1)(n+2)n! mod p=(2n1)(2n3)(n+3)((n+2)21)!2(2n(n+2)+1)/2+1 mod p(2n1)(2n3)(n+2)((n+1)2)!2(2n(n+3)+1)/2+1 mod pn0(mod 2),n1(mod 2).

因为取模的 p 不是素数,所以不能用逆元乱搞了。
我们可以用质因数分解的方法,将答案的唯一分解式算出来。
这里我想到了一个类似分治的方法。
我们可以用筛素数的方法,求出每个数 i 的最小质因子 k 和这个质因子是第几个质数 fi
设唯一分解式的第 i 个质数的指数为 ti,则 tfi 加一,然后分治处理 ik
然后就可以 A 了。


【Code】

[cpp]
  1. #include <iostream>  
  2. #include <cstdio>  
  3. #include <cstring>  
  4. #include <ctime>  
  5.   
  6. using namespace std;  
  7.   
  8. #define LL long long  
  9. typedef LL bign;  
  10.   
  11. LL tt[2000010];  
  12. LL prime[2000010];  
  13. LL first[2000010];  
  14. bool no_prime[2000010];   
  15.   
  16. LL n,m;  
  17. bign ans=1;  
  18.   
  19. LL power(LL x,LL y){  
  20.     if(y==0)return 1;  
  21.     if(y==1)return x%m;  
  22.     LL tmp=power(x%m,y/2);  
  23.     if(y&1)return tmp*tmp%m*(x%m)%m;  
  24.     else return tmp*tmp%m;   
  25. }  
  26.   
  27. void make1(LL x){  
  28.     while(1){  
  29.         if(x==1)return;  
  30.         if(prime[first[x]]==x){  
  31.             tt[first[x]]++;  
  32.             return;   
  33.         }  
  34.         else{  
  35.             while(x%prime[first[x]]==0){  
  36.                 tt[first[x]]++;  
  37.                 x/=prime[first[x]];  
  38.             }  
  39.         }  
  40.     }  
  41. }  
  42.   
  43. void make2(LL x){  
  44.     while(1){  
  45.         if(x==1)return;  
  46.         if(prime[first[x]]==x){  
  47.             tt[first[x]]–;  
  48.             return;  
  49.         }  
  50.         else{  
  51.             while(x%prime[first[x]]==0){  
  52.                 tt[first[x]]–;  
  53.                 x/=prime[first[x]];  
  54.             }  
  55.         }  
  56.     }  
  57. }  
  58.   
  59. void Pyh(){  
  60.     if(!(n&1)){  
  61.         tt[1]=(2*n-(n+2)+1)/2+1;  
  62.         for(LL i=n+3;i<=2*n-1;i+=2)make1(i);  
  63.         for(LL i=2;i<=(n+2)/2-1;i++)make2(i);  
  64.         for(LL i=1;i<=prime[0];i++)ans=ans*power(prime[i]%m,tt[i])%m;  
  65.         printf(”%lld\n”,ans%m);  
  66.     }  
  67.     else{  
  68.         tt[1]=(2*n-(n+3)+1)/2+1;  
  69.         for(LL i=n+2;i<=2*n-1;i+=2)make1(i);  
  70.         for(LL i=2;i<=(n+1)/2;i++)make2(i);  
  71.         for(LL i=1;i<=prime[0];i++)ans=ans*power(prime[i],tt[i])%m;  
  72.         printf(”%lld\n”,ans%m);   
  73.     }  
  74. }  
  75.   
  76. int main(){  
  77.       
  78.     scanf(”%lld%lld”,&n,&m);  
  79.     for(LL i=2;i<=2*n;i++){  
  80.         if(!no_prime[i]){  
  81.             prime[++prime[0]]=i;  
  82.             first[i]=prime[0];  
  83.         }  
  84.         LL j=1,t=i*prime[1];  
  85.         while(j<=prime[0]&&t<=2*n){  
  86.             first[t]=j;  
  87.             no_prime[t]=true;  
  88.             if(i%prime[j]==0)break;  
  89.             t=i*prime[++j];  
  90.         }  
  91.     }   
  92.     Pyh();  
  93.     return 0;  
  94. }  
版权声明:写得不好,随便转载,但请注明出处,感激不尽

相关文章推荐

有趣的数列[HNOI2009][Codevs2337]

题目描述 Description我们称一个长度为 2n 2n 的数列是有趣的,当且仅当该数列满足以下三个条件: ( 1 1 ) 它是从 1 1 到 2n 2n 共 2n 2n 个整数的一...

BZOJ 1485 HNOI 2009 有趣的数列 卡特兰数 线性筛法分解质因数

普通筛法应该是O(nlnn)O(n\ln n)的? 线性筛法才能过了。#include #define FOR(i,j,k) for(i=j;i<=k;++i) typedef long long...

数论——BZOJ1485[HNOI2009]有趣的数列

http://www.lydsy.com/JudgeOnline/problem.php?id=1485 这题我们可以先试试暴力求几个数的答案,或者也可以写一个递推O(n^2)(这样可以拿50分,虽...

1485 [HNOI2009] 有趣的数列 题解

【原题】 1485: [HNOI2009]有趣的数列 Time Limit: 10 Sec  Memory Limit: 64 MB Submit: 484  Solved: 272 [Submi...

[HNOI2009]有趣的数列

题目传送:衡阳八中http://61.187.179.132:8080/JudgeOnline/showproblem?problem_id=1485[HNOI2009]有趣的数列Time Limit...

BZOJ 2337 [HNOI2011] XOR和路径

期望+高斯消元

BZOJ 2337: [HNOI2011]XOR和路径|期望|高斯消元

高斯消元 按位计算 计算每一位的期望求和 被sb错误给坑了…… #include #include #include #include #include #include #include #incl...

bzoj2337: [HNOI2011]XOR和路径

传送门:http://www.lydsy.com:808/JudgeOnline/problem.php?id=2337 思路:看到异或,那就按位做。 假设现在在做第i位,为了描述方便,现在的边权...

BZOJ 2337 HNOI2011 XOR和路径 期望DP+高斯消元

题目大意:给定一个无向连通图,从1出发,每次等概率沿着任意一条出边走到n为止,求路径上的边权的异或和的期望值 首先既然是位运算的问题我们的一般处理办法就是拆位,按位处理 对于每一位 令f[i]为从i节...

BZOJ 2337|HNOI 2011|XOR和路径|概率期望|高斯消元

给定无向联通图,从1点等概率地向相邻点移动,求1点到N点的路径边权xor和的期望值。位运算一般拆位看。 对于每位的期望值显然有 E(u)=∑wu,v=0E(v)+∑wu,v=1[1−E(v)]di...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)