zoukankan      html  css  js  c++  java
  • [SDOI2017]数字表格 --- 套路反演

    [SDOI2017]数字表格

    由于使用markdown的关系
    我无法很好的掌控格式,见谅

    对于这么简单的一道题竟然能在洛谷混到黑,我感到无语

    [egin{align*} prodlimits^{n}_{i=1} prodlimits^{m}_{j=1} fi[gcd(i,j)] &= prodlimits^{n}_{d=1} fi[d]^{sumlimits_{e=1}^{n} [n/de][m/de]mu(e)} \ &= prodlimits^{n}_{T = 1} (prodlimits_{d|T} fi[d]^{mu(T/d)})^{[n/T][m/T]} end{align*}]

    两步化完式子后
    只要预处理函数(fprodlimits_{d|n} fi[d]^{mu(n/d)})的前缀积就行
    可以做到(O(n))(fi)(O(n))(mu),枚举因子(O(n logn))求这个函数,(O(n))计算前缀积
    为了方便,我们同时求出他们的逆元即可

    复杂度(O(n logn + Tsqrt n log n))

    代码

    #include <cstdio>
    #include <iostream>
    #define sid 1000050
    #define ll long long
    #define mod 1000000007
    #define ri register int
    using namespace std;
    
    const int N = 1000000;
    ll fi[sid], f[sid], iv[sid];
    int mu[sid], pr[sid], nop[sid], pp, tot;
    
    int read() { scanf("%d", &pp); return pp; }
    
    ll qpow(ll a, ll k) {
        ll ret = 1;
        while(k) {
            if(k & 1) ret = (ret * a) % mod;
            a = (a * a) % mod; k >>= 1;
        }
        return ret;
    }
    
    void Get_Fib() {
        fi[1] = 1; fi[2] = 1;
        for(ri i = 3; i <= N; i ++)
        fi[i] = (fi[i - 1] + fi[i - 2]) % mod;
    }
    
    void Get_Mu() {
        mu[1] = 1;
        for(ri i = 2; i <= N; i ++) {
            if(!nop[i]) { pr[++ tot] = i; mu[i] = -1; }
            for(ri j = 1; j <= tot; j ++) {
                int h = i * pr[j];
                if(h > N) break; nop[h] = 1;
                if(i % pr[j] == 0) { mu[h] = 0; break; }
                else mu[h] = -mu[i];
            }
        }
    }
    
    void Get_f() {
        for(ri i = 1; i <= N; i ++) f[i] = 1;
        for(ri i = 1; i <= N; i ++) {
            ll inv = qpow(fi[i], mod - 2);
            for(ri j = i; j <= N; j += i)
            if(mu[j / i] == -1) f[j] = (f[j] * inv) % mod;
            else if(mu[j / i]) f[j] = (f[j] * fi[i]) % mod;
        }
        f[0] = 1; iv[0] = 1;
        for(ri i = 1; i <= N; i ++) f[i] = (f[i] * f[i - 1]) % mod;
        for(ri i = 1; i <= N; i ++) iv[i] = qpow(f[i], mod - 2);
    }
    
    ll Solve(int n, int m) {
        ll ret = 1;
        if(n > m) swap(n, m);
        for(ri i = 1, j; i <= n; i = j + 1) {
            j = min(n / (n / i), m / (m / i));
            ret = ret * qpow(f[j] * iv[i - 1] % mod, 1ll * (n / i) * (m / i)) % mod;
        }
        return ret;
    }
    
    int main() {
        Get_Fib(); Get_Mu(); Get_f();
        int Tt = read();
        while(Tt --) {
            int n = read(), m = read();
            printf("%lld
    ", Solve(n, m));
        }
        return 0;
    }
    
  • 相关阅读:
    ZOJ 3818 Pretty Poem
    HDU 4597 Play Game
    HDU 4497 GCD and LCM
    CSU 1335 高桥和低桥
    UVA 10791 Minimum Sum LCM
    CSU 1119 Collecting Coins
    CSU 1120 病毒
    UVA 12169 Disgruntled Judge
    HDU 1301 Jungle Roads
    POJ 1258 Agri-Net
  • 原文地址:https://www.cnblogs.com/reverymoon/p/9189232.html
Copyright © 2011-2022 走看看