Mod
一、long long 乘法取模
核心思想
用long double 估计商的取值,然后任它溢出,它的真实答案和它%次方答案是一样的
$xym = xy-\dfrac{x*y}{m}*m$
代码
1 2 3 4 5 6 7 8 9
| ll mul(ll x,ll y,ll m) { x%=m;y%=m; ll d = ((long double)x*y/m); d = x*y-d*m; if(d>=m)d-=m; if(d<0)d+=m; return d; }
|
二、分数取模(没有逆元的情况)
例题:求
很容易发现的等比求和,
因为和不一定互质,因此可能不存在逆元
所以我们必须转化
$S = \dfrac{qq^{n-1}}{q-1}(q-1)S = qq^{n-1} mod (p*(q-1))$
现在用快速幂就能解决啦,最后再除以就是答案了
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| #include<bits/stdc++.h> using namespace std; typedef __int128 ll; ll q,n,p; ll ksm(ll a,ll b,ll p) { ll ans = 1,base = a; while(b) { if(b&1) { ans = ans*base%p; } base = base*base%p; b>>=1; } return ans%p; }
int main() { int t; cin>>t; while(t--) { long long x,y,z; cin>>x>>y>>z; q = x,n = y,p = z; p = p*(q-1); ll s = (ksm(q,n+1,p)-q)%p; s/=(q-1); cout<<(long long)s<<endl; } return 0; }
|
三、组合数取模(基本)
例题:回答T组询问,输出的值。
$C_{n}^{m} = \dfrac{n!}{m!(n-m)!}\dfrac{a}{b} \bmod pa \bmod p(b \bmod p)^{-1}$
即
$n!(m!)^{-1}(n-m)^{-1}$
%%
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
| #include<bits/stdc++.h> using namespace std; const int N = 1e7+10; const int mod = 1e9+7; typedef long long ll; ll fac[N],fnv[N];
ll ksm(ll a,ll b) { ll ans = 1,base = a; while(b>0) { if(b&1) { ans *= base; ans %= mod; } base *= base; base%=mod; b>>=1; } return ans; }
ll binom(int n,int m) { if(m<0||m>n)return 0; return fac[n]*fnv[m]%mod*fnv[n-m]%mod; }
int main() { fac[0] = 1; for(int i = 1;i<=N;i++) fac[i] = fac[i-1]*i%mod; fnv[N] = ksm(fac[N],mod-2); for(int i = N;i>=1;i--) fnv[i-1] = fnv[i]*i%mod; assert(fnv[0]==1); int t; cin>>t; while(t--) { int a,b; cin>>a>>b; cout<<binom(a,b)<<endl; } return 0; }
|
四、取模的封装
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| typedef long long ll; struct modular_arithmetic { const int mod = 998244353; int add(ll a, ll b) { return (a % mod + b % mod) % mod; } int mul(ll a, ll b) { return ((a % mod) * (b % mod)) % mod; } int pow(ll x, ll n) { if (n == 0) return 1; int res = pow(x, n / 2); res = mul(res, res); if (n % 2) res = mul(x, res); return res; } int inv(ll x) { return pow(x, mod - 2); } int div(ll a, ll b) { return mul(a, inv(b)); } }; modular_arithmetic mod;
|