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

      

    1485: [HNOI2009]有趣的数列

    Time Limit: 10 Sec  Memory Limit: 64 MB
    Submit: 1284  Solved: 688
    [Submit][Status][Discuss]

    Description

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

    Input

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

    Output

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

    Sample Input

    3 10

    Sample Output

    5

     
    这道题正着想很不好想,所以我们可以倒过来想。
    把[1,2n]的排列当成2n个位置,原数列中每个位置当成一个数x,那么考虑从1到2n依次填现在的每个位置。

    然后就很好做了,对于每个奇数的x,填完后一定是有序的,偶数同理,所以可以把奇数视为0,偶数视为1,得到一个合法的01序列后一定可以按顺序还原出数列。

    那么当前填了a个0,a+1个1,那么说明原数列中有个位置2i选了,而2i-1还没选,则a[2i-1]>a[2i],显然是违法的。

    因为每个时刻0>1,通项为卡特兰数列。

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 #define ll long long
     6 #define N 2000005
     7 using namespace std;
     8 int n,p;
     9 int su[N],tot,pr[N],fan[N];
    10 const int inf = 2000000;
    11 void shai()
    12 {
    13     for(int i=2;i<=inf;i++)
    14     {
    15         if(!pr[i])
    16         {
    17             su[++tot]=i;
    18             fan[i]=tot;
    19             pr[i]=i;
    20         }
    21         for(int j=1;j<=tot&&su[j]<=pr[i]&&su[j]*i<=inf;j++)
    22         {
    23             pr[su[j]*i]=su[j];
    24         }
    25     }
    26     return ;
    27 }
    28 int num[N];
    29 inline void fft(int x,int z)
    30 {
    31     while(x!=1)
    32     {
    33         num[fan[pr[x]]]+=z;
    34         x/=pr[x];
    35     }
    36     return ;
    37 }
    38 int main()
    39 {
    40     scanf("%d%d",&n,&p);
    41     shai();
    42     for(int i=2;i<=n*2;i++)fft(i,1);
    43     for(int i=2;i<=n;i++)fft(i,-2);
    44     fft(n+1,-1);
    45     ll ans=1;
    46     for(int i=1;i<=tot;i++)
    47     {
    48         for(int j=1;j<=num[i];j++)
    49         {
    50             ans=ans*su[i]%p;
    51         }
    52     }
    53     printf("%lld
    ",ans);
    54     return 0;
    55 }

      

      

  • 相关阅读:
    Write an algorithm such that if an element in an MxN matrix is 0, its entire row and column is set to 0.
    旋转二维数组
    replace empty char with new string,unsafe method和native implementation的性能比较
    判断一字符串是否可以另一字符串重新排列而成
    移除重复字符的几个算法简单比较
    也来纠结一下字符串翻转
    判断重复字符存在:更有意义一点
    程序员常去网站汇总
    sublime
    针对程序集 'SqlServerTime' 的 ALTER ASSEMBLY 失败,因为程序集 'SqlServerTime' 未获授权(PERMISSION_SET = EXTERNAL_ACCESS)
  • 原文地址:https://www.cnblogs.com/ezyzy/p/6586130.html
Copyright © 2011-2022 走看看