• P3807 【模板】卢卡斯定理


    P3807 【模板】卢卡斯定理

    (C_{m + n}^{m} \% p) ( (1le n,m,ple 10^5) )


    错误日志: 数组开小(哇啊啊啊洼地hi阿偶我姑父阿贺佛奥UFO爱我帮你)


    Pre

    好的我们继续恶补数学
    首先复习一下 (O(N)) 求质数逆元的方法$$inv[1] = 1$$$$inv[i] = (p - p / i) * inv[p % i] % p (i >= 2)$$

    LL inv[maxn];
    void get_inv(LL n){
    	inv[1] = 1;
    	for(LL i = 2;i <= n;i++)inv[i] = (p - p / i) * inv[p % i] % p;
    	}
    

    然后是 (O(m))(C_{n}^{m} \% p):$$C_{n}^{m}% p = frac{n!}{m!(n - m)!}% p$$$$=frac{(n - m + 1) * (n - m +2) * ... * n}{m!}% p$$$$=(frac{n - m + 1}{1}% p) * (frac{n - m + 2}{2}% p) * ... * (frac{n}{m}% p)$$
    其中除法取模可以用上面的逆元计算, 求解一个组合数的复杂度为 (O(m))

    LL C(LL n, LL m){
    	LL ans = 1;
    	for(LL i = 1;i <= m;i++)ans = ans * (n - m + i) * inv[i] % p;
    	return ans;
    	}
    

    最后就是卢卡斯定理, 当 (p) 为质数时有:$$C_{n}^{m} % p = C_{n % p}^{m % p} * C_{n / p}^{m / p} % p$$
    其中取模过了的部分可以很快的计算出来, 另一部分继续递归卢卡斯即可

    LL lucas(LL n, LL m, LL p){
    	if(m == 0)return 1;
    	return C(n % p, m % p) * lucas(n / p, m / p, p) % p;
    	}
    

    Solution

    于是乎掌握了上边的知识后就变成裸题啦

    Code

    #include<iostream>
    #include<cstdio>
    #include<queue>
    #include<cstring>
    #include<algorithm>
    #include<climits>
    #define LL long long
    using namespace std;
    LL RD(){
        LL out = 0,flag = 1;char c = getchar();
        while(c < '0' || c >'9'){if(c == '-')flag = -1;c = getchar();}
        while(c >= '0' && c <= '9'){out = out * 10 + c - '0';c = getchar();}
        return flag * out;
        }
    const LL maxn = 200019;
    LL n, m, p;
    LL inv[maxn];
    void get_inv(LL n){
    	inv[1] = 1;
    	for(LL i = 2;i <= n;i++)inv[i] = (p - p / i) * inv[p % i] % p;
    	}
    LL C(LL n, LL m){
    	LL ans = 1;
    	for(LL i = 1;i <= m;i++)ans = ans * (n - m + i) * inv[i] % p;
    	return ans;
    	}
    LL lucas(LL n, LL m, LL p){
    	if(m == 0)return 1;
    	return C(n % p, m % p) * lucas(n / p, m / p, p) % p;
    	}
    int main(){
    	LL T = RD();
    	while(T--){
    		n = RD(), m = RD(), p = RD();
    		get_inv(m);
    		printf("%lld
    ", lucas(n + m, m, p));
    		}
    	return 0;
    	}
    
  • 相关阅读:
    web框架和Django框架的初识
    外键的变种,单表的查询,多表的查询
    数据库的安装与初识
    响应式设计中几个class区别
    Velocity+Java较全教程
    Web开发基础
    AutoCompleteTextView不能使用的问题
    Http中Cookie与Set-Cookie头
    Java Web 乱码
    Karel运行环境配置
  • 原文地址:https://www.cnblogs.com/Tony-Double-Sky/p/9532173.html
Copyright © 2020-2023  润新知