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

    题面:[HNOI2009]有趣的数列

    题解:

      观察到题目其实就是要求从长为2n的序列中选n个放在集合a,剩下的放在集合b,使得集合a和集合b中可以一一对应的使a中的元素小于b。

      2种想法(实质上是一样的)。

      1,相当于前1位中至少要选1个放入a,前3位中至少要选2位放入a,前5位中至少要选3位放入a......前2n - 1位中恰好选n位放入a。

      2,用0表示放入a集合,1表示放入b集合。则每个1都必须有一个左边的0与之匹配,相当于对于任意位置前面0的个数大于等于1的个数。

      不管是哪种,其实都可以看做括号匹配问题。。。。。。所以就是卡特兰数了

      因为n比较大,且p不一定为质数,因此可以用一个数组存下每个质因子有几个,对于乘法就累加,除法就减掉,然后把最后剩下的累乘起来就是答案。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define R register int
     4 #define AC 2001000
     5 #define maxn 2000000
     6 #define LL long long
     7 
     8 int tot, n, p;
     9 int pri[AC], last[AC];
    10 LL have[AC], ans;
    11 bool ispri[AC];
    12 
    13 void get()
    14 {
    15     last[1] = 1;
    16     for(R i = 2; i <= maxn; i ++)
    17     {
    18         if(!ispri[i]) pri[++ tot] = i, last[i] = i;
    19         for(R j = 1; j <= tot; j ++)
    20         {
    21             int now = pri[j];
    22             if(i * now > maxn) break;
    23             ispri[i * now] = true, last[i * now] = now;
    24             if(!(i % now)) break;
    25         }
    26     }
    27 }
    28 
    29 void pre(){
    30     scanf("%d%d", &n, &p);
    31 }
    32 
    33 inline void cal(int x){//分解质因数
    34     while(last[x] != 1) ++ have[last[x]], x /= last[x];
    35 }
    36 
    37 inline void cut(int x){
    38     while(last[x] != 1) -- have[last[x]], x /= last[x];
    39 }
    40 
    41 inline LL qpow(LL x, int have)
    42 {
    43     LL ans = 1;
    44     while(have)
    45     {
    46         if(have & 1) ans = ans * x % p;
    47         x = x * x % p, have >>= 1;
    48     }
    49     return ans;
    50 }
    51 
    52 void work()
    53 {
    54     int b = 2 * n;
    55     for(R i = 1; i <= b; i ++) cal(i);
    56     for(R i = 1; i <= n; i ++) cut(i), cut(i);
    57     cut(n + 1), ans = 1;
    58     for(R i = 1; i <= b; i ++)
    59         if(have[i]) ans = ans * qpow(i, have[i]) % p;
    60     printf("%lld
    ", ans);
    61 }
    62 
    63 int main()
    64 {
    65 //    freopen("in.in", "r", stdin);
    66     get();
    67     pre();
    68     work();
    69 //    fclose(stdin);
    70     return 0;
    71 }
    View Code
  • 相关阅读:
    数据库chapter 4 数据库安全性
    数据库 chapter 2 关系数据库
    数据库 chapter 1 概论
    操作系统 chapter 11 I/O系统
    操作系统 chapter 12 死锁
    操作系统 chapter 7 8 存储模型
    聊一聊移动调试那些事儿
    获取当前日期和农历的js代码
    使用 CSS 媒体查询创建响应式网站
    大前端工具集
  • 原文地址:https://www.cnblogs.com/ww3113306/p/9919969.html
Copyright © 2011-2022 走看看