【Lucas组合数定理】组合-FZU 2020

组合 FZU-2020

题目描述

给出组合数C(n,m), 表示从n个元素中选出m个元素的方案数。例如C(5,2) = 10, C(4,2) = 6.可是当n,m比较大的时候,C(n,m)很大!于是xiaobo希望你输出 C(n,m) mod p的值!

分析

Lucas定理:
如果我们要求C(n,m)%p的值,那么

进行推导可以得到

这一道题使用Lucas定理的递归式
\[ C^n_m \ mod \ p= C^{n\ mod \ p}_{m\ mod \ p}\times C^{n\div p}_{m\div p} \ mod \ p\]

Lucas递归边界,\(m=0\) 那么值就是1,其余部分递归处理,
剩下的$ C(n%mod,m%mod) $就可以使用费马小定理或者扩展欧几里得来求出逆元算一下答案就可以了。

AC代码

#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>
#include <cctype>
#include <cmath>
#include <time.h>
#include <map>
#include <set>
#include <vector>
using namespace std;
#define ms(a,b) memset(a,b,sizeof(a))
typedef long long ll;
ll n,m,p;
inline int read(){
    int X=0,w=0; char ch=0;
    while(!isdigit(ch)) {w|=ch=='-';ch=getchar();}
    while(isdigit(ch)) X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
    return w?-X:X;
}
ll power(ll a,ll b) {
    ll res=1;
    while(b>0) {
        if (b&1) res=res*a%p;
        b=b>>1;
        a=a*a%p;
    }
    return res;
}
ll C(ll n,ll m) {
    if (m>n) return 0;
    ll ans=1;
    for (int i=1;i<=m;i++) {
        ll a=(n+i-m)%p;
        ll b=i%p;
        ans=ans*(a*power(b,p-2)%p)%p;
    }
    return ans;
}
ll lucas(ll n,ll m) {
    if (m==0) return 1;
    return C(n%p,m%p)*lucas(n/p,m/p)%p;
}
int main(){
    int cas=read();
    while (cas--) {
        scanf("%lld%lld%lld",&n,&m,&p);
        printf("%lld\n",lucas(n,m));
    }
    return 0;
}

原文地址:https://www.cnblogs.com/Dawn-Star/p/9612578.html

时间: 2024-07-29 11:00:50

【Lucas组合数定理】组合-FZU 2020的相关文章

FZU 2020 组合 (Lucas定理)

题意:中文题. 析:直接运用Lucas定理即可.但是FZU好奇怪啊,我开个常数都CE,弄的工CE了十几次,在vj上还不显示. 代码如下: #pragma comment(linker, "/STACK:1024000000,1024000000") #include <cstdio> #include <string> #include <cstdlib> #include <cmath> #include <iostream>

FZU 2020 :组合 【lucas】

Problem Description 给出组合数C(n,m), 表示从n个元素中选出m个元素的方案数.例如C(5,2) = 10, C(4,2) = 6.可是当n,m比较大的时候,C(n,m)很大!于是xiaobo希望你输出 C(n,m) mod p的值! 思路:水题,练一下lucas #include<iostream>#include<cstdio>#include <math.h>#include<algorithm>#include<stri

[Lucas定理][组合] Bzoj P4403 序列统计

Description 给定三个正整数N.L和R,统计长度在1到N之间,元素大小都在L到R之间的单调不降序列的数量.输出答案对10^6+3取模的结果. 题解 我们要求长度为n的元素在[1..r-l+1]中的单调不下降序列的数量 考虑将第i个元素加上i-1,那么每个合法序列就会对应一个长度为n,元素为[1..n+m-1]中的单调递增的序列数量 显然两者是一一对应的,那么就只用统计后面的贡献 那么就是在n+m-1个元素中选n个,就是C(n+m-1,n) 所以答案就是C(m,n+m)-1,然后用luc

文章标题 fzu 2020

Problem 2020 组合 Accept: 623 Submit: 1533 Time Limit: 1000 mSec Memory Limit : 32768 KB Problem Description 给出组合数C(n,m), 表示从n个元素中选出m个元素的方案数.例如C(5,2) = 10, C(4,2) = 6.可是当n,m比较大的时候,C(n,m)很大!于是xiaobo希望你输出 C(n,m) mod p的值! Input 输入数据第一行是一个正整数T,表示数据组数 (T <=

[Lucas][树形dp][组合] Bzoj P2111 Perm 排列计数

Description 称一个1,2,...,N的排列P1,P2...,Pn是Magic的,当且仅当2<=i<=N时,Pi>Pi/2. 计算1,2,...N的排列中有多少是Magic的,答案可能很大,只能输出模P以后的值 题解 把i/2看作i和i+1的父亲,然后这样就会形成一棵完全二叉树 那么就可以考虑树形dp,设f[i]表示从i到n的方案数,size[i]表示第i个数的子树大小 那么如果i*2>n,那么f[i]=1,如果i*2==n,那么f[i]=f[i*2] 如果i*2+1&l

FZU 2020-组合(Lucas定理+逆元解决大组合数求模)

题目地址:FZU 2020 题意:求C(n,m)%p的值(1 <= m <= n <= 10^9, m <= 10^4, m < p < 10^9, p是素数). 思路: 对于和并且p是素数,我们一般采用Lucas定理来解. 1).Lucas定理是用来求 C(n,m) mod p的值,p是素数.其描述为: 如果 那么得到 即 Lucas(n,m,p)=C(n%p,m%p)* Lucas(n/p,m/p,p) Lucas(n,0,p)=1; 2).对于大组合数求模C(N,

组合 Lucas定理

组合 Time Limit: 1000MS   Memory Limit: 32768KB   64bit IO Format: %I64d & %I64u [Submit]   [Go Back]   [Status] Description 给出组合数C(n,m), 表示从n个元素中选出m个元素的方案数.例如C(5,2) = 10, C(4,2) = 6.可是当n,m比较大的时候,C(n,m)很大!于是xiaobo希望你输出 C(n,m) mod p的值! Input 输入数据第一行是一个正

Problem 2020 组合(FOJ)

Problem 2020 组合 Accept: 714    Submit: 1724Time Limit: 1000 mSec    Memory Limit : 32768 KB  Problem Description 给出组合数C(n,m), 表示从n个元素中选出m个元素的方案数.例如C(5,2) = 10, C(4,2) = 6.可是当n,m比较大的时候,C(n,m)很大!于是xiaobo希望你输出 C(n,m) mod p的值!  Input 输入数据第一行是一个正整数T,表示数据组

定理总结

余数: 1>同余:若a , b除以c的余数相等,则a与b相对于除数c是同余的,即a≡ b(mod c)! 2>同余的两个数的差能整除除数:如 10 % 3 = 1, 7 % 3 = 1,10≡ 7 (mod 3)则(10 - 7 )% 3 = 0.3>余数可加性(可减性同):两个数对于某个除数的余数和对此除数的余数等于两个数的和对此除数的余数!如 (11 % 3 + 8 % 3 )% 3= (11 + 8) % 34>两个数对某个除数的余的乘积对此除数的余数等于两个数的乘积对此除数