ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Perm 排列计数

2019-07-03 15:44:45  阅读:252  来源: 互联网

标签:排列 return lucas int ll Perm 计数 fac size


排列组合这部分确实很水,但关键是想到树,堆。

i与2×i,2×i+1有关,符合树上节点编号的特点,加上大小限制就是堆的性质了。

这个堆中存的是节点编号所以大小固定,每个节点的size[i]固定往里边填数(排列组合部分);

设f[i]是以i为根的组合方案数,

f[i]=f[i*2]*f[i*2+1]*C(size[i]-1,size[2*i]),在符合比i大的数里随机选size[2*i]个分给左树,剩下的是右数。

n,m很大用lucas定理。

C(n,m)%p=C(n%p,m%p)*C(n/p,m/p);

递归:lucas(n,m)( =C(n,m)%p )=C(n%p,m%p)*lucas(n/p,m/p)%p;

阶乘可以打表。虽然P可能到1e9,但n%p,一定小于n,所以打到n就完事了。

逆元部分可打表也可快速幂:

根据费马小定理。

p为质,x^p-1同余1(mod p);所以x*x^p-2同余1;x的逆元就是x^p-2;

ll C(int n,int m)
{
    if(m>n) return 0;
    return fac[n]*qpow(fac[m]*fac[n-m]%p,p-2)%p;
}

%p也可以在快速幂里写但不能忽略,因为a*a%p这可能会炸...WA36原因。

1不是质数不考虑。

 

总结:树编号的特点灵活用,知识间的结合,观察数列,数,编号的特点疯狂联想。

          lucas定理。

          mod p要考虑清楚是否需要是否可能炸。

#include<cstdio>
#include<iostream>
using namespace std;
#define ll long long
const int maxn=2e6+5;
int n,p,size[maxn];
ll f[maxn],fac[maxn];
void init()
{
    fac[0]=1;
    int turn=min(n,p);
    for(int i=1;i<=turn;i++)
        fac[i]=fac[i-1]*i%p;
}
ll qpow(ll a,int b)
{
    ll ans=1;
    while(b)
    {
        if(b&1) ans=ans*a%p;
        b>>=1;
        a=a*a%p;
    }
    return ans;
}
ll C(int n,int m)
{
    if(m>n) return 0;
    return fac[n]*qpow(fac[m]*fac[n-m]%p,p-2)%p;
}
ll lucas(int n,int m)
{
   if(!m) return 1;
   return C(n%p,m%p)*lucas(n/p,m/p)%p;
}
ll F(int x)
{
    if(x>n) return 1;
    f[x]=( F(2*x)*F(2*x+1) )%p *lucas(size[x]-1,size[2*x]) %p;
    return f[x];
}
int Size(int x)
{
    if(x>n) return 0;
    size[x]=Size(2*x)+Size(2*x+1)+1;
    return size[x];
}
int main()
{
    scanf("%d%d",&n,&p);
    if(p==1)
    {
        printf("0");
        return 0;
    }
    init();
    size[1]=Size(1);
    f[1]=F(1);
    printf("%lld",f[1]);
}
View Code

 

标签:排列,return,lucas,int,ll,Perm,计数,fac,size
来源: https://www.cnblogs.com/three-D/p/11126738.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有