• [ZJOI2010]Perm 排列计数


     

     题概:

      题目描述

      称一个1,2,...,N的排列P1,P2...,Pn是Magic的,当且仅当2<=i<=N时,Pi>Pi/2.

      计算1,2,...N的排列中有多少是Magic的,答案可能很大,只能输出模P以后的值

      输入格式

      输入文件的第一行包含两个整数 n和p,含义如上所述。

      输出格式

      输出文件中仅包含一个整数,表示计算1,2,?, ???的排列中, Magic排列的个数模 p的值。

      样例

      样例输入

      20 23

      样例输出

      16

      数据范围与提示

      100%的数据中,1 ≤ ??? N ≤ 106, P??? ≤ 10^9,p是一个质数。 数据有所加强

     
    分析:
      主要意思就是在
      1-n的序列里找到P(i)>P(i/2)
      可以想到二叉堆满足
      父亲比儿子优的性质
      所以即维护小根堆从root到叶子的路满足一个magic序列
      (1)首先是DP
      因为儿子之间是可以交换的
      所以有不同的二叉树
      DP即是求二叉树的种数
      dp[i]=dp[i*2]*dp[i*2+1]*C(size[i]-1,size[left]);
      始终没有理解式子
      其实
      这样一个小根堆的size,形状都是相对确定的
      根据乘法原理
      有两个儿子相乘
      另外,考虑两个儿子树中的任意节点可交换
      因此有*C(size[i]-1,size[left])
      (2)可以看到
      1 ≤ ??? N ≤ 106, P??? ≤ 10^9
      这样的数据范围
      需要有lucas
      博主因实力太菜
      实际上花了半天在调lucas
    最后
     
    #include<iostream>
    #include<cstdio>
    #define ll long long
    #define MAXN 2000010
    using namespace std;
    int n;
    ll p;
    ll jc[MAXN];
    ll dp[MAXN];
    int size[MAXN];
    ll pow(ll a,ll b){
        ll ans=1;
        while(b){
            if(b&1)ans=(ans*a)%p;
            a=(a*a)%p;
            b>>=1;
        }
        return ans%p;
    }
    ll C(int a,int b){
        if(a<b)return 0;
        if(b==0)return 1;
        return jc[a]*pow(jc[a-b]*jc[b]%p,p-2)%p;
    }
    ll lucas(int a,int b){
        if(b>a)return 0;
        if(b==0)return 1;
        if(a>p||b>p)return C(a%p,b%p)*lucas(a/p,b/p)%p;
        return C(a,b)%p;
    }
    void dfs(ll u){
        if(u>n){
            dp[u]=1;
            return ;
        }
        dfs(u<<1);
        dfs(u<<1|1);
        size[u]=size[u<<1]+size[u<<1|1]+1;
        dp[u]=dp[u<<1]*dp[u<<1|1]%p*lucas(size[u]-1,size[u<<1])%p;
        return ;
    }
    int main(){
        scanf("%d%lld",&n,&p);
        jc[0]=1;
        for(int i=1;i<=n;++i)jc[i]=jc[i-1]*1ll*i%p;
        dfs(1);
        printf("%lld
    ",dp[1]%p);
    }
    View Code

     

  • 相关阅读:
    PL/SQL编程基本概念
    oracle基本笔记整理及案例分析2
    oracle基本笔记整理及案例分析2
    oracle基本笔记整理及案例分析2
    oracle基本笔记整理及案例分析1
    oracle基本笔记整理及案例分析1
    oracle基本笔记整理及案例分析1
    oracle笔记整理2
    oracle笔记整理2
    oracle笔记整理2
  • 原文地址:https://www.cnblogs.com/2018hzoicyf/p/11112672.html
Copyright © 2020-2023  润新知