痛定思痛
由于前期没有认真的考虑学过的算法的使用限制,造成了区域赛的夺银擦肩。于是,我决定没一个我学习过的算法都认真总结,分析。
组合数的求解一般有三种:
一、杨辉三角法
二、Lucas暴力求解
三、Lucas打表法
第一种就这里就略过。
第二种
给出的C(N,M) % P ,这时候的N,P都很大,没发打表。而M相对来说比较小。所以,此时我们可以运用暴力的求解方法。这里的数据范围一般是(N < 10^18,P < 10^9),M < 10^5 (P要为素数)
#include <iostream> #include <algorithm> #include <cstdio> #include <cmath> #include <cstring> using namespace std; typedef long long LL; LL N,M,P; LL powmod(LL a,LL b,LL p){ LL res = 1; a %= p; while(b > 0){ if(b & 1) res = res * a % p; a = a * a % p; b >>= 1; } return res; } //暴力循环求解 LL Norma_C(LL n,LL m,LL p){ LL ans = 1; for(int i = 1;i <= m;++i){ LL a = (n + i - m) % p; LL b = i % p; ans = ans * (a * powmod(b,p-2,p) % p) % p; } return ans; } LL Lucas(LL n,LL m,LL p){ if(!m) return 1; if(n%p < m%p) return 0; LL tmp = Norma_C(n%p,m%p,p); return tmp * Lucas(n / p,m / p,p); } int main() { int T; scanf("%d",&T); while(T--){ scanf("%I64d%I64d%I64d",&N,&M,&P); printf("%I64d\n",Lucas(N,M,P)); } return 0; }
时间: 2024-11-09 05:38:34