快速幂
ll pow_mod(ll x,ll n,ll mod){ll res=1;while(n){if(n&1)res=res*x%mod;x=x*x%mod;n>>=1;}return res;}//xµÄn´Î·½mod template<typename T>void read(T &res){bool flag=false;char ch;while(!isdigit(ch=getchar()))(ch=='-')&&(flag=true); for(res=ch-48;isdigit(ch=getchar());res=(res<<1)+(res<<3)+ch - 48);flag&&(res=-res);}
矩阵快速幂
const int MAXN = 10; #define int long long #define ll long long struct Matrix { ll mat[MAXN][MAXN]; }; Matrix P; Matrix I; //单位矩阵 Matrix Mul_Matrix(Matrix a, Matrix b , ll mod) { Matrix c; for(int i = 0 ; i < MAXN ; i ++) for(int j = 0 ; j < MAXN ; j ++) { c.mat[i][j] = 0; for(int k = 0 ; k < MAXN ; k ++) { c.mat[i][j] += (a.mat[i][k] * b.mat[k][j]) % mod; c.mat[i][j] %= mod; } } return c; } Matrix pow_mod_Matrix(Matrix P , ll n , ll mod) { Matrix ans = I, b = P; while(n) { if(n & 1) ans = Mul_Matrix(ans , b , mod); n >>= 1; b = Mul_Matrix(b , b , mod); } return ans; } void Matrix_init() { for(int i = 0 ; i < MAXN ; i ++) I.mat[i][i] = 1; }
gcd+lcm
int gcd(int a,int b){return !b?a:gcd(b,a%b);} int lcm(int a,int b){return a/gcd(a,b)*b;} ///上面的大数被卡了,可以用下面的 int gcd(int a , int b) { if(a == 0)return 1; if(a < 0) return gcd(-a , b); while(b) { ll t = a % b; a = b; b = t; } return a; }
逆元
int inv_exgcd(int x , int mod) { int a , b; int re = exgcd(x , mod , a , b); if(a < 0) a += (-x / (mod / re) + 1) * (mod / re); return a; } int inv_pow(int x , int mod) { return pow_mod(x , mod - 2 , mod); }
exgcd
int exgcd(int a , int b , int &x , int &y){ if(! b){ x = 1 , y = 0; return a; } int re = exgcd(b , a % b , y , x); y -= (a / b) * x; return re; } /* ax + by = c x *= c / gcd(a , b) y *= c/ gcd(a , b) 任意解 : x = x0 + b / gcd(a , b) * t y = y0 - a / gcd(a , b) * t t 为任意数 最小整数解x(y): ((x * c / gcd(a , b)) % (b / gcd(a , b)) + (b / gcd(a , b))) % (b / gcd(a , b)) */
中国剩余定理crt(带龟速乘)
int exgcd(int a , int b , int &x , int &y){ if(! b){ x = 1 , y = 0; return a; } int re = exgcd(b , a % b , y , x); y -= (a / b) * x; return re; } int Slow_Mul(int x , int y , int mod)///快速乘,避免爆ll { int ans = 0; int flag = 1; if((x < 0 && y > 0) || (x > 0 && y < 0))flag = -1; x = abs(x) , y = abs(y); while(y) { if(y & 1)ans += x % mod , ans %= mod; y >>= 1; x = (x + x) % mod; } return ((ans * flag) % mod + mod) % mod; } int Li[maxn] , Ti[maxn] , a[maxn] , b[maxn]; int crt(int a[] , int b[] , int n) /// n个数 , a是除数 , b是余数 , 除数互质 { int L = 1; for(int i = 1 ; i <= n ; i ++) L *= a[i]; for(int i = 1 ; i <= n ; i ++) Li[i] = L / a[i]; for(int i = 1 ; i <= n ; i ++){ int x , y; int re = exgcd(Li[i] , a[i] , x , y); Ti[i] = x; } int ans = 0; for(int i = 1 ; i <= n ; i ++) ans += Slow_Mul(Slow_Mul(Li[i] , Ti[i] , L) , b[i] , L) , ans %= L; return (ans + L) % L; }
扩展中国剩余定理excrt(带龟速乘)
int exgcd(int a , int b , int &x , int &y){ if(! b){ x = 1 , y = 0; return a; } int re = exgcd(b , a % b , y , x); y -= (a / b) * x; return re; } int inv_exgcd(int x , int mod) { int a , b; int re = exgcd(x , mod , a , b); if(a < 0) a += (-x / (mod / re) + 1) * (mod / re); return a; } int inv_pow(int x , int mod) { return pow_mod(x , mod - 2 , mod); } int Slow_Mul(int x , int y , int mod)///快速乘,避免爆ll { int ans = 0; int flag = 1; if((x < 0 && y > 0) || (x > 0 && y < 0))flag = -1; x = abs(x) , y = abs(y); while(y) { if(y & 1)ans += x % mod , ans %= mod; y >>= 1; x = (x + x) % mod; } return ((ans * flag) % mod + mod) % mod; } int excrt(int a[] , int b[] , int n) /// n个数 , a是除数 , b是余数 , 除数不互质 { for(int i = 2 ; i <= n ; i ++) { int a1 = a[i - 1] , a2 = a[i] , b1 = b[i - 1] , b2 = b[i]; int re = gcd(a1 , a2);///11 if(abs(b2 - b1) % re != 0) return -1; a[i] = a1 / re * a2; b[i] = Slow_Mul(Slow_Mul(inv_exgcd(a1 / re , a2 / re) , ((b2 - b1) / re) , (a2 / re)) , a1 , a[i]) + b1 % a[i]; b[i] = (b[i] % a[i] + a[i]) % a[i]; } return b[n]; }
Pointard_Rhod定理(大数质因子分解)
#define int long long int S = 50; int Slow_Mod(int a , int b , int mod) { a %= mod , b %= mod; int res = 0; while(b) { if(b & 1)res += a , res %= mod; a <<= 1 , a %= mod; b >>= 1; } return res; } //计算 x^n %c int pow_mod(int x , int n , int mod)//x^n%c { x %= mod , n %= mod; int res = 1; while(n) { if(n & 1) res = Slow_Mod(res , x , mod); x = Slow_Mod(x , x , mod); n >>= 1; } return res; } //以a为基,n-1=x*2^t a^(n-1)=1(mod n) 验证n是不是合数 //一定是合数返回true,不一定返回false bool check(int a , int n , int x , int t) { int res = pow_mod(a , x , n); int last = res; for(int i = 1 ; i <= t ; i ++) { res = Slow_Mod(res , res , n); if(res == 1 && last != 1 && last != n - 1) return true;//合数 last = res; } if(res != 1) return true; return false; } // Miinter_Rabin()算法素数判定 //是素数返回true.(可能是伪素数,但概率极小) //合数返回false; bool Miinter_Rabin(int n) { if(n < 2)return false; if(n == 2)return true; if((n & 1) == 0) return false;//偶数 int x = n - 1; int t = 0; while((x & 1) == 0) x >>= 1 , t ++; for(int i = 0 ; i < S ; i ++) { int a = rand() % (n - 1) + 1;//rand()需要stdlib.h头文件 if(check(a , n , x , t)) return false;//合数 } return true; } //************************************************ //pointard_rho 算法进行质因数分解,先判是否是素数,特判 1、2 //************************************************ int Fac[100];//质因数分解结果(刚返回时是无序的) int tol;//质因数的个数。数组小标从0开始 int gcd(int a , int b)///不要用迭代会TLE { if(a == 0)return 1; if(a < 0) return gcd(-a , b); while(b) { int t = a % b; a = b; b = t; } return a; } int Pointard_Rho(int x , int c) { int i = 1 , k = 2; int x0 = rand() % x; int y = x0; while(1) { i ++; x0 = (Slow_Mod(x0 , x0 , x) + c) % x; int d = gcd(y - x0 , x); if(d != 1 && d != x) return d; if(y == x0) return x; if(i == k)y = x0 , k += k; } } //对n进行素因子分解 , 特判2,先用米勒罗宾判是不是质数 void Find_Prime_Fac(int n) { if(Miinter_Rabin(n))//素数 { Fac[tol ++]=n; return; } int p = n; while(p >= n)p = Pointard_Rho(p , rand() % (n - 1) + 1); Find_Prime_Fac(p); Find_Prime_Fac(n / p); }
欧拉筛
int prime[maxn],minprime[maxn]; int euler(int n) {int c=0,i,j;for(i=2;i<=n;i++){if(!minprime[i])prime[++c]=i,minprime[i]=i;for(j=1;j<=c&&i*prime[j]<=n;j++) {minprime[i*prime[j]]=prime[j];if(i%prime[j]==0)break;}}return c;}
积性函数线性筛
void init() { low[1] = f[1] = 1; for(int i = 2 ; i <= maxn - 10 ; i ++){ if(!vis[i]){ vis[i] = 1 , low[i] = i , f[i] = 2 * i - 1 , prime[++ cnt] = i , k[i] = 1; ////low->最小质因子(带指数)即p1^k1 , f->积性函数 , k -> 记录次方,即最小质因子的指数是多少 } for(int j = 1 ; j <= cnt && prime[j] * i < maxn ; j ++){ vis[prime[j] * i] = 1; if(i % prime[j] == 0){///即 gcd(i , prime[j]) = p1 low[i * prime[j]] = low[i] * prime[j];///p1^k1再乘上一个p1 if(low[i] == i){///是否 是p^k k[prime[j] * i] = k[i] + 1; ///p^k公式 f[i * prime[j]] = (k[i * prime[j]] + 1) * i * prime[j] - k[i * prime[j]] * i; } else{/// prime[j]==p1 f[i * prime[j]] = f[i / low[i]] * f[low[i] * prime[j]];///另一个公式 } break; } else{ f[i * prime[j]] = f[i] * f[prime[j]]; low[i * prime[j]] = prime[j];//prime[j] < p1 } } } }