[lnsyoj668/luoguP3807]Lucas定理
题意
原题链接
求
sol
Lucas定理:
证明(源自OI-wiki)
考虑 的取值,注意到,分子的质因子分解中 的次数恰好为 ,因此只有当 或 的时候 的质因子分解中含有 ,因此
。进而我们可以得出
注意过程中没有用到费马小定理,因此这一推导不仅适用于整数,亦适用于多项式。因此我们可以考虑二项式 的结果
考虑二项式 ,那么 就是求其在 次项的取值。使用上述引理,我们可以得到
注意前者只有在 的倍数位置才有取值,而后者最高次项为 ,因此这两部分的卷积在任何一个位置只有最多一种方式贡献取值,即在前者部分取 的倍数次项,后者部分取剩余项,即
看不懂没关系,蒟蒻也看不懂
那么解决这道题就很简单了,只需要使用递归依次枚举,的情况返回,且的情况直接计算(通过预处理来解决)就可以了
代码
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
const int N = 100005;
long long inv[N], f[N], fi[N];
void init(long long p){
f[0] = fi[0] = 1;
inv[1] = f[1] = fi[1] = 1;
for (long long i = 2; i <= p; i ++ ){
inv[i] = (p - p / i) * inv[p % i] % p;
f[i] = f[i - 1] * i % p;
fi[i] = fi[i - 1] * inv[i] % p;
}
}
long long lucas(long long m, long long n, long long p){
if (m < n) return 0;
if (m <= p && n <= p) return f[m] * fi[n] % p * fi[m - n] % p;
return lucas(m / p, n / p, p) * lucas(m % p, n % p, p) % p;
}
int main(){
long long n, m, p;
int T;
cin >> T;
while (T -- ){
cin >> n >> m >> p;
init(p);
cout << lucas(n + m, n, p) << endl;
}
return 0;
}
分类:
题解 / 2024训练
标签:
数学
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现