逆元简介
,可以称a
是b
在模p
情况下的逆元.
逆元其实就是可以看作倒数
阶乘逆元
方式一:
通过费马小定理求逆元:
当p
为素数,并且gcd(a,p)=1
时,我们有。那么就有,则a
的逆元就是
下面ksm
函数为快速幂
fact[0] = 1;
for(int i = 1; i < N; i++)
{
fact[i] = fact[i - 1] * i % mod;
inv[i] = ksm(fact[i], mod - 2);
}
方式二:
通过式子倒推接近线性求阶乘逆元
其实就可以看作的逆元
for(int i = 1; i <= n; i++)
fact[i] = fact[i - 1] * i % mod;
inv[n] = ksm(fact[n], mod - 2);
for(int i = n - 1; i >= 1; i--)
inv[i] = inv[i + 1] * (i + 1) % mod;
线性求逆元
求关于mod
的逆元时,可以做到在时间内解决
设模数为p
对于当前的i
,设 ,则
注意:
一定要初始化为1,需要从2开始递推,不能从1开始递推
inv[0] = inv[1] = 1;
for(int i = 2; i < N; i++)
inv[i] = inv[mod % i] * (mod - mod / i) % mod;
同时可以通过线性求逆元求阶乘逆元:
只需要再将逆元用类似阶乘的形式乘起来即可,求得的inv[i]
即为的逆元
for(int i = 2; i < N; i++)
inv[i] = inv[i - 1] * inv[i] % mod;
组合数计算
计算
- 方式一:公式计算
计算都是在逆元或者阶乘基础上计算的
ll C(ll n, ll m)
{
if(n < m) return 0;
return fact[n] * inv[m] % mod * inv[n - m] % mod;
}
- 方式二:递推方式
需要建表,所以如果计算范围比较大时需要的空间也大
递推公式 :
for(int i = 1; i <= n; i++)
for(int j = 0; j <= i; j++)
{
if(i == j || j == 0) c[i][j] = 1;
else c[i][j] = c[i - 1][j - 1] + c[i - 1][j];
}
题目
链接:https://ac.nowcoder.com/acm/contest/23481/J
题目描述:求
就是在数组中选中k个值相乘,最后把结果相加即可
因为数组中的数大小只有三种情况。所以可以根据这个进行切入口。
首先可以不用考虑,接下考虑有个和个,如果上述和式中出现了个,那么需要出现个,于是答案为
代码中注意各种初始化
线性求逆元中初始化:inv[1] = 1
fac[i]
:
fact[i]
:
#include<bits/stdc++.h>
using namespace std;
using ll = long long;
const int N = 1e7 + 5, mod = 998244353;
ll fac[N], fact[N], inv[N];
ll C(ll n, ll m)
{
if(n < m) return 0;
return fact[n] * inv[m] % mod * inv[n - m] % mod;
}
void solve()
{
fac[1] = 2;
fac[0] = fact[0] = fact[1] = inv[0] = inv[1] = 1;
for(int i = 2; i < N; i++)
{
fac[i] = fac[i - 1] * 2 % mod;
fact[i] = fact[i - 1] * i % mod;
inv[i] = inv[mod % i] * (mod - mod / i) % mod;
}
for(int i = 2; i < N; i++)
inv[i] = inv[i - 1] * inv[i] % mod;
int n, k;
cin >> n >> k;
vector<int> a(n);
int o = 0, t = 0;
for(int i = 0; i < n; i++)
{
cin >> a[i];
if(a[i] == 1) o ++;
else if(a[i] == 2) t ++;
}
ll res = 0;
for(int i = 0; i <= k; i++)
{
res += C(o, i) * C(t, k - i) % mod * fac[k - i] % mod;
res %= mod;
}
cout << res << "\n";
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
int t;
// cin >> t;
t = 1;
while(t--) solve();
return 0;
}