#include<bits/stdc++.h>usingnamespace std;typedeflonglong ll;const ll maxn =1e6+100;
ll r[maxn];//余数
ll m[maxn];//除数
ll n;
ll mul(ll a, ll b, ll mod){
ll res =0ll;while(b){if(b &1)res =(res + a)% mod;
a =(a + a)% mod;
b >>=1;}return res % mod;}
ll exgcd(ll a, ll b, ll& x, ll& y){if(b ==0){
x =1;
y =0;return a;}
ll d =exgcd(b, a % b, y, x);
y -=(a / b)* x;return d;}
ll exchina(){
ll M = m[1], res = r[1];
ll a, b, c, d, x, y, t;for(ll i =2; i <= n; i++){
a = M, b = m[i], c =((r[i]- res)% m[i]+ m[i])% m[i];
d =exgcd(a, b, x, y);if(c % d)return-1;
t = b / d;//x = x * c / d;//x = (x % t + t) % t;
x =mul(x, c / d, t);
res += x * M;
M *= t;
res =(res % M + M)% M;}return res;}intmain(){
ios::sync_with_stdio(false);
cin >> n;for(ll i =1; i <= n; i++){
cin >> m[i]>> r[i];}
ll ans =exchina();
cout << ans << endl;return0;}
解同余方程(中国-除数互质)
#include<bits/stdc++.h>usingnamespace std;typedeflonglong ll;const ll maxn =1000005ll;
ll pri[maxn];
ll r[maxn];
ll n;
ll exgcd(ll a, ll b, ll& x, ll& y){if(b ==0){
x =1;
y =0;return a;}
ll res =exgcd(b, a % b, y, x);
y -=(a / b)* x;return res;}
ll china(ll pri[], ll r[], ll n){
ll temp =1ll;
ll res =0ll;for(ll i =0; i < n; i++){
temp *= pri[i];}for(ll i =0; i < n; i++){
ll m = temp / pri[i];
ll x, y;
ll d =exgcd(pri[i], m, x, y);
res =(res + y * m * r[i])% temp;}return(res % temp + temp)% temp;}intmain(){
ios::sync_with_stdio(false);
cin >> n;for(ll i =0; i < n; i++){
cin >> pri[i]>> r[i];}
ll ans =china(pri, r, n);
cout << ans << endl;return0;}
矩阵快速幂
#include<bits/stdc++.h>usingnamespace std;typedeflonglong ll;
ll x, y, aa, bb, mod;
string s;structM{staticconstint maxn =2;
ll a[2][2];M(){
a[0][0]= a[1][1]=1;
a[0][1]= a[1][0]=0;}
M operator*(const M& b){
M res;
res.a[0][0]=(a[0][0]* b.a[0][0]+ a[0][1]* b.a[1][0])% mod;
res.a[0][1]=(a[0][0]* b.a[0][1]+ a[0][1]* b.a[1][1])% mod;
res.a[1][0]=(a[1][0]* b.a[0][0]+ a[1][1]* b.a[1][0])% mod;
res.a[1][1]=(a[1][0]* b.a[0][1]+ a[1][1]* b.a[1][1])% mod;return res;}};
M ksm(M A,int k){if(!k)returnM();
M res;while(k){if(k &1)res = res * A;
A = A * A;
k >>=1;}return res;}
M ksm(M A, string s){
M res;for(int i = s.length()-1; i >=0; i--){if(s[i]!='0')res = res *ksm(A, s[i]-'0');
A =ksm(A,10);}return res;}intmain(){
ios::sync_with_stdio(false);
cin >> x >> y >> aa >> bb;
cin >> s >> mod;
M A;
A.a[0][0]= aa;
A.a[0][1]= bb;
A.a[1][0]=1;
A.a[1][1]=0;
A =ksm(A, s);
ll ans =((A.a[1][0]* y)% mod +(A.a[1][1]* x)% mod)% mod;
cout << ans << endl;return0;}
费马小定理:若 p 是质数,且 gcd(a,p)=1 ,则有 a^(p-1)=1(mod p)
从逆元的定义推导,可得 a*inv(a)=1=a^(p-1)(mod p) ,于是有 inv(a)=a^(p-2)(mod p)。
p为质数!!!
#include<bits/stdc++.h>usingnamespace std;typedeflonglong ll;
ll a, p;
ll ksm(ll x, ll y, ll mod){
ll ans =1ll;while(y){if(y &1)ans =(ans * x)% mod;
x =(x * x)% mod;
y >>=1;}return ans % mod;}
ll inv(ll a, ll p){returnksm(a, p -2, p);}intmain(){
ios::sync_with_stdio(false);
cin >> a >> p;
cout <<inv(a, p)<< endl;return0;}
求逆元(线性递推)
给定n,p,求1到n在模p意义下的乘法逆元 n<=3e6
线性递推证明:
设p=aq+r,即q=p/a ,r=p%a
aq+r=0(mod p)
a=-r*inv(q)(mod p)inv(a)=-q*inv(r)(mod p)
得线性递推公式 inv(a)=-(p/a)*inv(p%a)
洛谷P3811
#include<bits/stdc++.h>usingnamespace std;typedeflonglong ll;const ll maxn =3e6+10;
ll inv[maxn];
ll n, p;intmain(){
ios::sync_with_stdio(false);
cin >> n >> p;
inv[1]=1ll;for(ll i =2; i <= n; i++){
inv[i]=(((ll)(-p / i + p)% p)* inv[p % i])% p;}for(ll i =1; i <= n; i++)cout << inv[i]<< endl;return0;}
求逆元和求特解(扩展欧几里得)
//题目 洛谷P1082
exgcd应用:1.求ax+by=gcd(a,b)的特解(x,y) 2.求ax=1(mod m)的a的逆元x
#include<bits/stdc++.h>usingnamespace std;typedeflonglong ll;//求方程ax+by=gcd(a,b)的特解,特别的ax+by=1有解当且仅当a,b互质
ll exgcd(ll a, ll b, ll& x, ll& y){if(b ==0){
x =1;
y =0;return a;}
ll d =exgcd(b, a % b, y, x);
y -=(a / b)* x;return d;}//求满足ax%m=1(ax+my=1或称ax=1(mod m)),称x为a在模m意义下的逆元,求x//a和m互质时,才有a的逆元x
ll inv(ll a, ll m){
ll x, y;
ll d =exgcd(a, m, x, y);if(d ==1)return(x + m)% m;elsereturn-1;}
ll a, b;intmain(){
ios::sync_with_stdio(false);
cin >> a >> b;
cout <<inv(a, b)<< endl;return0;}
求排列组合数(求一次)(卢卡斯定理)
//卢卡斯定理求组合数#include<bits/stdc++.h>usingnamespace std;typedeflonglong ll;
ll n, m, p;
ll ksm(ll a, ll b, ll mod){
ll temp =1ll;while(b){if(b &1)temp =(temp * a)% mod;
a =(a * a)% mod;
b >>=1;}return temp % mod;}
ll fermat_inv(ll x, ll mod){returnksm(x, mod -2, mod)% mod;}
ll C(ll n, ll m){if(n < m)return0;
m =min(m, n - m);
ll a =1ll;
ll b =1ll;for(ll i =0; i < m; i++){
a =(a *(n - i))% p;
b =(b *(i +1))% p;}return a *fermat_inv(b, p)% p;}
ll lucas(ll n, ll m){if(m ==0)return1;returnlucas(n / p, m / p)*C(n % p, m % p)% p;}intmain(){
ios::sync_with_stdio(false);int t;
cin >> t;while(t--){
cin >> n >> m >> p;
cout <<lucas(n, m)<< endl;}return0;}
求排列组合数(求多次)
//根据题目大意推出表达式,主要是求阶乘逆元的操作#include<bits/stdc++.h>usingnamespace std;typedeflonglong ll;const ll maxn =2e5+100;
ll mod =998244353;
ll fac[maxn];
ll inv[maxn];
ll n, m, k;
ll ans;voidinverse(ll n){
inv[1]=1;for(ll i =2; i <= n; i++)inv[i]=(mod - mod / i)* inv[mod % i]% mod;}voidinit(ll n){
fac[0]= inv[0]=1;inverse(n);for(ll i =1; i <= n; i++){
fac[i]= fac[i -1]* i % mod;
inv[i]= inv[i -1]* inv[i]% mod;}}
ll c(ll n, ll m){return fac[n]* inv[m]% mod * inv[n - m]% mod;}
ll ksm(ll a, ll b){
ll res =1ll;while(b){if(b &1)res = res * a % mod;
a = a * a % mod;
b >>=1;}return res % mod;}intmain(){
ios::sync_with_stdio(false);
cin >> n >> m >> k;init(n);
ll p =ksm(m -1, n -1- k);for(ll i = k; i >=0; i--){
ans =(ans +c(n -1, i)* m % mod * p % mod)% mod;
p = p *(m -1)% mod;}
cout << ans << endl;return0;}
开__int128(排列组合数过大)
#include<bits/stdc++.h>usingnamespace std;typedeflonglong ll;voidscan(__int128 &x){//输入
x =0;int f =1;char ch;if((ch =getchar())=='-') f =-f;else x = x *10+ ch -'0';while((ch =getchar())>='0'&& ch <='9')
x = x *10+ ch -'0';
x *= f;}void_print(__int128 x){if(x >9)_print(x /10);putchar(x %10+'0');}voidprint(__int128 x){//输出if(x <0){
x =-x;putchar('-');}_print(x);}
__int128 n, k;
解同余方程(扩中-除数不互质)#include<bits/stdc++.h>using namespace std;typedef long long ll;const ll maxn = 1e6 + 100;ll r[maxn];//余数ll m[maxn];//除数ll n;ll mul(ll a, ll b, ll mod){ ll res = 0ll; while (b) { if (b & 1)res = (res + a) % mod; a =