标签:base 合数 等于 string sys return n+1 str 效率
计算
快速幂就是快速算底数的k
次幂,时间复杂度为O(logk)
与朴素算法相比效率极大提升。
原理
将k
转化成二进制数
11
的二进制数为1011
则十进制11
写成
当k=11
时,
将\(a^k=a^{11}\)写成
代码实现:
int qmi(int a, int k, int p) {
long res = 1, base = a;
while(k != 0) {
if((k & 1) == 1) res = res * a % p;
k >>= 1;
a = a * a % p;
}
return (int) res;
}
int comb01(int n, int m) {
long res = 1;
for(int i=1; i <= m; i++) {
res = res * (n-m+i) / i;
}
return (int) res;
}
2.性质法
一个物品有两种选择,要么选要么不选,n个中选m个的方案数(\(C_n^m\))等于当前一个物品不选的方案数(\(C_{n-1}^{m}\))和选当前物品的方案数(\(C_{n-1}^{m-1}\))的和。
int comb02(int n, int m, int p) {
int[][] c = new int[n+1][m+1];
for(int i=0; i <= n; i++) {
for(int j=0; j <= i && j <= m; j++) {
if(j==0) c[i][j] = 1;
else c[i][j] = (c[i-1][j-1] + c[i-1][j]) % p;
}
}
return c[n][m];
}
3.预处理逆元法
预处理出阶乘取模的余数fact[N],和阶乘取模的逆元infact[N]
如果取模的数是质数,可以使用费马小定理求逆元
费马小定理:若p为素数,则有\(a^{p-1}\equiv1\ (\mod p)\)
即:
\(a^{p-2}\)就是a在\(\mod p\)意义下的逆元。
如果多次计算
long[] fact, infact;
int N;
int p = 1000000007;//必须为素数
void init(int n, int p){
N = 1001;// 必须N大于恒大于n
fact = new long[N];
infact = new long[N];
fact[0] = infact[0] = 1;
for(int i=1; i < N; i++) {
fact[i] = fact[i-1]*i % p;
infact[i] = qmi((int)fact[i], p-2, p);
}
//System.out.println(Arrays.toString(fact));
//System.out.println(Arrays.toString(infact));
}
int comb03(int n, int m, int p) {
init(p);
long res = fact[n] * infact[n-m] % p * infact[m] % p;
return (int)res;
}
或者计算一次
int p = 1000000007;//必须为素数
long ans1 = 1L, ans2 = 1L;//组合数的分子和分母
for(int i=n; i >= n-m+1; i--)
ans1 = ans1 * i % p;
for(int i=1; i <= s; i++)
ans2 = ans2 * i % p;
ans2 = qmi((int)ans2, p-2, p);
int comb = ans1*ans2%p;
标签:base 合数 等于 string sys return n+1 str 效率
原文地址:https://www.cnblogs.com/lixyuan/p/12909275.html