lucas定理 学习笔记
lucas定理 学习笔记
介绍
lucas定理用于解决形如
的问题。
设
则:
例如下面这道题 oj
combination
题目描述
LMZ有n个不同的基友,他每天晚上要选m个一起玩,而且要求每天晚上的选择都不一样。那么LMZ能够持续多少个这样的夜晚呢?当然,LMZ的一年有10007天,所以他想知道答案mod 10007的值。(1<=m<=n<=200,000,000)
输入格式
第一行一个整数t,表示有t组数据。(t<=200) 接下来t行每行两个整数n, m,如题意。
输出格式
T行,每行一个数,为C(n, m) mod 10007的答案。
样例
输入样例1
4
5 1
5 2
7 3
4 2
输出样例2
5
10
35
6
分析
显然,答案就是:
但是我们的
所以我们就可以用 lucas 定理减小空间
code
#include <bits/stdc++.h>
#define LL long long
#define fu(x , y , z) for (int x = y ; x <= z ; x ++)
#define fd(x , y , z) for (int x = y ; x >= z ; x --)
using namespace std;
const int mod = 10007;
LL fac[mod + 5] , inv[mod + 5] , n , m;
LL ksm (LL x , LL y) {
if(!y)
return 1;
long long z = ksm (x , y / 2);
z = z * z % mod;
if (y & 1)
z = z * x % mod;
return z;
}
void pre () {
fac[0] = fac[1] = 1;
for(int i = 2 ; i <= mod - 1 ; i++)
fac[i] = fac[i - 1] * i % mod;
inv[mod - 1] = ksm (fac[mod - 1] , mod - 2);
for (int i = mod - 2 ; i >= 0 ; i --)
inv[i] = inv[i + 1] * (i + 1) % mod;
}
LL C (LL x , LL y) {
if (x < y) return 0;
if (!y || x == y) return 1;
return fac[x] * inv[y] % mod * inv[x - y] % mod;
}
LL lucas (LL x , LL y) {
if (x < y) return 0;
if (!y) return 1;
if (x < mod && y < mod) return C (x , y);
return lucas (x / mod , y / mod) * C (x % mod , y % mod) % mod;
}
int main () {
pre ();
int T;
scanf ("%d" , &T);
while (T --) {
scanf ("%lld%lld" , &n , &m);
printf ("%lld\n" , lucas (n , m));
}
}
扩展lucas
未完待续
如果人生会有很长,愿有你的荣耀永不散场
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 周边上新:园子的第一款马克杯温暖上架
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?
· 使用C#创建一个MCP客户端