数学

组合数

ll inv[N],inc[N];
void init(){
    inc[0]=1;
    for(int i=1;i<=N;i++){
        inc[i]=inc[i-1]*i % mod;
    }
    inv[0]=1;
    for(int i=1;i<=N;i++){
        inv[i]=powmod(inc[i],mod-2);
    }
}
ll C(int a,int b){    
    if(a<b) return 0;
    return inc[a]*inv[a-b]%mod*inv[b]%mod;
}
ll Catalan(int n,int m){
    return (C(n + m,n) - C(n + m,m - 1) + mod) % mod;
}

矩阵

template<class T, const int SZ> struct Matrix {
    typedef Matrix Mat;
    array<array<T, SZ>, SZ> d{};
    Mat operator*(const Mat& mat) const {
        Mat a;
        for (int i = 0; i < SZ; i++) {
            for (int j = 0; j < SZ; j++) {
                for (int k = 0; k < SZ; k++) {
                    a.d[i][j] += d[i][k]*mat.d[k][j];
                }
            }
        }
        return a;
    }
    vector<T> operator*(const vector<T>& vec) const {
        vector<T> ret(SZ);
        for (int i = 0; i < SZ; i++) {
            for (int j = 0; j < SZ; j++) {
                ret[i] += d[i][j] * vec[j];
            }
        }
        return ret;
    }
    Mat operator^(ll p) const {
        assert(p >= 0);
        Mat a, b(*this);
        for (int i = 0; i < SZ; i++) a.d[i][i] = 1;
        while (p) {
            if (p&1) a = a * b;
            b = b * b;
            p >>= 1;
        }
        return a;
    }
};

扩展欧几里得

int exgcd(int a, int b, int &x, int &y){
    if (b == 0) {
        x=1, y=0;
        return a;
    }
    int xx, yy;
    int d = exgcd(b, a%b, xx, yy);
    x = yy;
    y = xx - (a / b) * yy;
    return d;
} 
int calc(int a, int b) {
    int x, y;
    int d = exgcd(a, b, x, y);
    b /= d;
    if(b < 0) b = -b;
    int cnt = x % b;
    if (cnt < 0) cnt += b;
    return cnt;
}

乘法逆元

long long inv[N];
void Inv(){
    inv[1]=1;
    int ans=1;
    for(int i=2;i<=N;i++){    
        inv[i]=(mod-mod/i)*inv[mod%i]%mod;
    }
}

线性筛

constexpr int N=50000000;
int pr[N/5], p[N+100], tot;
int n;
void prime(){
    p[1] = 1;
    for(int i = 2; i <= N; i++){
        if(!p[i]) p[i]=i, pr[++tot] = i;
        for(int j=1; j <= tot && i * pr[j] <= N; j++){
            p[i * pr[j]] = pr[j];
            if(pr[j] == p[i]) break;
        }
    }
}

解同余方程组

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;
}

void merge(ll &a, ll &b, ll c, ll d) {
    if (a == -1 && b == -1) return;
    ll x, y;
    ll g = exgcd(b, d, x, y);
    if ((c - a) % g != 0) {
        a = b = -1;
    } 
    d /= g;
    ll t0 = ((c - a) / g) % d * x % d;
    while (t0 < 0) t0 += d;
    a = b * t0 + a;
    b = b * d;
}

void solve() {
    ll a = 0, b = 1; //x mod b=a
    int n; cin >> n;
    for (int i = 1; i <= n; i++) {
        ll c, d; cin >> c >> d;
        merge(a, b, d, c);
    }
    cout << a << endl;
}

积性函数

#include <bits/stdc++.h>
using namespace std;
constexpr int N=20100000;
int pr[N/5], p[N], pe[N], tot;
int n, ans, f[N];

void compute(int n, function<void(int)> calcpe) {
    f[1] = 1;
    for (int i = 2; i <= n; i++) {
        if (i == pe[i]) calcpe(i);
        else f[i] = f[pe[i]] * f[i / pe[i]];
    }
}

int main() {
    cin >> n;
    p[1] = 1;
    for(int i = 2; i <= n; i++){
        if(!p[i]) p[i] = i, pe[i] = i, pr[++tot] = i;
        for(int j=1; j <= tot && i * pr[j] <= n; j++){
            p[i * pr[j]] = pr[j];
            if(pr[j] == p[i]) {
                pe[i * pr[j]] = pe[i] * pr[j];
                break;
            } else {
                pe[i * pr[j]] = pr[j];
            }
        }
    }
    compute(n, [&](int x){
        f[x] = f[x / p[x]] + 1;
    });//D(i)
    compute(n, [&](int x){
        f[x] = f[x / p[x]] + x;
    });//Sigma(i)
    compute(n, [&](int x){
        f[x] = x / p[x] * (p[x] - 1);
    });//Phi(i)
    compute(n, [&](int x){
        f[x] = ((f[x] == x) ? -1 : 0);
    });//Mu(i)
    return 0;
}

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
constexpr int N = 200010;
ll powmod(ll a,ll b,ll mod) {ll res=1;a%=mod;for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}

int pf[N];
int main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    cin.exceptions(cin.failbit);
    int p, t;
    cin >> p >> t;
    int m = p - 1;
    int k = 0;
    for (int i = 2; i * i <= m; i++) {
        if (m % i == 0) {
            pf[k++] = i;
            while(m % i == 0) m /= i;
        }
    }
    if (m != 1) pf[k++] = m;
    while (t--) {
        int a;
        cin >> a;
        int d = p - 1;
        for (int i = 0; i < k; i++) {
            while ((d % pf[i] == 0) && powmod(a, d / pf[i], p) == 1)    
                d /= pf[i];
        }
        cout << d << "\n";
    }
    return 0;
}    

原根

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
constexpr int N = 200010;
ll powmod(ll a,ll b,ll mod) {ll res=1;a%=mod;for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}

int pf[N];
int main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    cin.exceptions(cin.failbit);
    int t;
    cin >> t;
    while (t--) {
        int p;
        cin >> p;
        int m = p - 1, k = 0;
        for (int i = 2; i * i <= m; i++) {
            if (m % i == 0) {
                pf[k++] = i;
                while(m % i == 0) m /= i;
            }
        }
        if (m != 1) pf[k++] = m;
        int d = p - 1;
        for (int g = 1; g < p; g++){
            bool vaild = true;
            for (int i = 0; i < k; i++) {
                if (powmod(g, d / pf[i], p) == 1)    
                    vaild = false;
            }
            if (vaild) {
                cout << g << "\n";
                break;
            }
        }
    }
    return 0;
}    

指数方程

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
constexpr int N = 200010;
ll powmod(ll a,ll b,ll mod) {ll res=1;a%=mod;for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}

int a, b, m;

void solve() {
    cin >> a >> b >> m;
    int T = sqrt(m) + 2;
    unordered_map<int, int> hs;
    ll v = powmod(a, T, m), d = 1;
    for (int q = 1; q <= T; q++) {
        d = d * v % m;
        if (!hs.count(d)) hs[d] = q * T;
    }
    int ans = m + 1;
    d = b;
    for (int r = 1; r <= T; r++) {
        d = d * a % m;
        if (hs.count(d)) ans = min(ans, hs[d] - r);
    }
    if (ans >= m) {
        cout << "-1\n";
    } else {
        cout << ans << "\n";
    }
}

int main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    cin.exceptions(cin.failbit);
    int t;
    cin >> t;
    while (t--) {
        solve();
    }
    return 0;
}    

莫比乌斯反演

#include <bits/stdc++.h>
using namespace std;
constexpr int N=20100000;
int pr[N/5], p[N], pe[N], tot;
int n, ans, f[N], mu[N], g[N];

int main() {
    cin >> n;
    p[1] = 1, mu[1] = 1;
    for(int i = 2; i <= n; i++){
        if(!p[i]) p[i] = i, mu[i] = -1, pr[++tot] = i;
        for(int j=1; j <= tot && i * pr[j] <= n; j++){
            p[i * pr[j]] = pr[j];
            if(pr[j] == p[i]) {
                pe[i * pr[j]] = 0;
                break;
            } else {
                pe[i * pr[j]] = -mu[i];
            }
        }
    }
    //g = f * mu;
    //g[n] = sum_{d|n} f[d] * mu[n / d]
    //g[n] = sum_{n = d1 * d2} f[d1] * mu[d2]
    for (int d1 = 1; d1 <= n; d1++) {
        for (int d2 = 1; d1 * d2 <= n; d2++) {
            g[d1 * d2] += f[d1] * mu[d2];
        }
    }

    return 0;
}

 

posted @ 2024-03-21 21:33  Miburo  阅读(14)  评论(0)    收藏  举报