zoukankan      html  css  js  c++  java
  • Perm排列计数

    B. Perm 排列计数

    内存限制:512 MiB 时间限制:1000 ms 标准输入输出
     

    题目描述

    称一个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为根

      一个点的任意一个子孙一直除2的话最终都会到该点,即在以该点为根的子树内,该点值最小  

      假设有n个点,父亲要最小的那一个,左右儿子各自成家,互不干扰,左儿子要剩下的n-1个中的m个,剩下的都给了右儿子一家,组合数为C(n-1,m),向下一个个分下去你会发现

      转移式为 f[爹]=f[左儿子]*f[右儿子]*C(size[],size[])  f[]表示满足条件的组合数,size[]表示以该点为根的树的大小  

      因为n有点大,n!会炸掉,所以求组合数的时候上Lucas定理就欧了

      弱弱的Lockey死活不用Lucas(我牛逼,我伟大),一直在搞高精乘低精,高精除低精,但还是在强悍的Lucas面前献上了膝盖%%%%

      

    #include<iostream>
    #include<cstdio>
    using namespace std;
    int n,p,son[110000000],d[100000000];
    long long ans=1;
    long long pow(long long a,long long b,long long p){
        long long ans=1;
        a%=p;
        while(b){
            if(b&1) ans=(ans*a)%p;
            b>>=1;
            a=(a%p)*(a%p)%p;
        }
        ans%=p;
        return ans;
    }
    long long inv(long long x,long long p){
        return pow(x,p-2,p);
    }
    long long C(long long n,long long m){
        if(m>n) return 0;
        long long up=1,down=1;
        for(int i=n-m+1;i<=n;i++) up=up*i%p;
        for(int i=1;i<=m;i++) down=down*i%p;
        return up*inv(down,p)%p;
    }
    long long Lucas(long long n,long long m,long long p){
        if(m==0) return 1;
        return C(n%p,m%p)*Lucas(n/p,m/p,p);
    }
    void dfs(int x){
        if(2*x<=n)    dfs(2*x);
        if(2*x+1<=n) dfs(2*x+1);
        son[x]=son[2*x]+son[2*x+1]+1;
        if(son[x]>2){
            ans=(long long)(ans%p)*(long long)(Lucas(son[x]-1,son[2*x]?son[2*x]:son[2*x+1],p)%p)%p;
        }
        return;
    }
    int main(){
        scanf("%d%d",&n,&p);
        if(n==1){
            cout<<1%p;
            return 0;
        }
        dfs(1);
        cout<<ans%p;
    }
    $Will$ $Be$ $The$ $King$
  • 相关阅读:
    【精品软件】小蔡电脑助手 V2.0
    C++ 数据结构与算法(二)线性表之单链表
    C++ 数据结构与算法:冒泡排序及改进算法
    C++ 数据结构与算法(四)线性表之循环链表
    const int *p、int*const p、和 int const *p 详解
    C++ 指针和引用的区别
    C++ 数据结构与算法(三)线性表之双向链表
    C++ 数据结构与算法(一)线性表之顺序表
    C++数据结构与算法:选择排序
    VC++ 获取文件夹大小
  • 原文地址:https://www.cnblogs.com/heoitys/p/11110659.html
Copyright © 2011-2022 走看看