有趣的数列 [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. }  
版权声明:写得不好,随便转载,但请注明出处,感激不尽

1485 [HNOI2009] 有趣的数列 题解

【原题】 1485: [HNOI2009]有趣的数列 Time Limit: 10 Sec  Memory Limit: 64 MB Submit: 484  Solved: 272 [Submi...
  • u013724185
  • u013724185
  • 2014年04月18日 13:03
  • 1284

BZOJ系列1485《[HNOI2009]有趣的数列》题解

Description  我们称一个长度为2n的数列是有趣的,当且仅当该数列满足以下三个条件:     (1)它是从1到2n共2n个整数的一个排列{ai};     (2)所有的奇数项满足a132n...
  • Dante__Alighieri
  • Dante__Alighieri
  • 2015年03月28日 13:29
  • 320

BZOJ 1485: [HNOI2009]有趣的数列 卡特兰数

Description我们称一个长度为2n的数列是有趣的,当且仅当该数列满足以下三个条件:(1)它是从1到2n共2n个整数的一个排列{ai};(2)所有的奇数项满足a1...
  • just_sort
  • just_sort
  • 2017年05月06日 12:07
  • 157

bzoj 1485: [HNOI2009]有趣的数列 (卡特兰数)

1485: [HNOI2009]有趣的数列 Time Limit: 10 Sec  Memory Limit: 64 MB Submit: 1226  Solved: 652 [Submit][...
  • clover_hxy
  • clover_hxy
  • 2017年02月15日 09:45
  • 176

bzoj 1485: [HNOI2009]有趣的数列 卡特兰数

题意我们称一个长度为2n的数列是有趣的,当且仅当该数列满足以下三个条件:我们称一个长度为2n的数列是有趣的,当且仅当该数列满足以下三个条件: (1)它是从1到2n共2n个整数的一个排列ai; ...
  • qq_33229466
  • qq_33229466
  • 2017年03月07日 15:10
  • 320

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

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

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

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

bzoj1486 [HNOI2009]最小圈 【最小比例环 01分数规划】

链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1486 题意:中文题,和上题相似,求的是sigma(c)/k最小的环,c是边的权值,k为选了多...
  • u012483216
  • u012483216
  • 2016年08月01日 13:11
  • 274

点分治专题——bzoj 1468 &bzoj 2152 题解

【前言】最近一直在忙着学算法,但是效果似乎不是很好。前段时间的树剖也快忘了= =。树套树没熟练,就开始写主席树了= =。更别说本身就不是很懂的莫比乌斯反演了。~~决定好好复习一下。 【点分治的作用】套...
  • u013724185
  • u013724185
  • 2014年05月13日 20:50
  • 3209

【bzoj2989】【数列】【cdq分治+树状数组】

Description 给定一个长度为n的正整数数列a[i]。 定义2个位置的graze值为两者位置差与数值差的和,即graze(x,y)=|x-y|+|a[x]-a[y]|。 2种操作...
  • sunshinezff
  • sunshinezff
  • 2016年06月29日 11:46
  • 492
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:有趣的数列 [Codevs 2337,Bzoj 1485,HNOI2009]
举报原因:
原因补充:

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