ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

【题解】洛谷 P3704 [SDOI2017]数字表格

2021-03-15 22:03:00  阅读:174  来源: 互联网

标签:lfloor frac limits 题解 sum rfloor P3704 洛谷 prod


目录

前置

幂转和

\(\prod\limits_{i} g^{d_i}=g^{\sum\limits_{i}d_i}\),\(g\) 是常数,或者至少在这次 \(\prod\) 中不会变化

gcd 的套路卷积

\[\begin{aligned} \because[x==1]&=\sum\limits_{d|x}\mu(d)\\ \therefore[gcd(x, y)==1]&=\sum\limits_{d|gcd(x, y)}\mu(d) \\&=\sum\limits_{d}\mu(d)[d|x][d|y] \end{aligned} \]

此时常常可以将 \(\sum\limits_{d}\mu(d)\) 提到式子最前面,而 \([d|x][d|y]\) 常常可以与枚举 \(x, y\) 的上界进行抵消,就像这样:

\(\sum\limits_{x=1}^{n}[x|d]\mathbf{f}(x)=\sum\limits_{x=1}^{\lfloor\frac{n}{d}\rfloor}\mathbf{f}(xd)\)

而当 \(\mathbf{f}(x)=\mathbf{1}(x)=1\) 时,原式 \(=\lfloor\frac{n}{d}\rfloor\)

推公式

\[\begin{aligned} \prod\limits_{i=1}^{n}\prod\limits_{j=1}^{m}f_{gcd(i,j)} &=\prod\limits_{i=1}^{n}\prod\limits_{j=1}^{m}\prod\limits_{g=1}^{\min(i, j)}f_g^{[gcd(i, j)==g]} \\&=\prod\limits_{g=1}^{\min(n, m)}f_g^{\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{m}[gcd(i, j)==g]} \\&=\prod\limits_{g=1}^{\min(n, m)}f_g^{\sum\limits_{i=1}^{\lfloor\frac{n}{g}\rfloor}\sum\limits_{j=1}^{\lfloor\frac{m}{g}\rfloor}[gcd(i, j)==1]} \\&=\prod\limits_{g=1}^{\min(n, m)}f_g^{\sum\limits_{i=1}^{\lfloor\frac{n}{g}\rfloor}\sum\limits_{j=1}^{\lfloor\frac{m}{g}\rfloor}\sum\limits_{d|gcd(i, j)}\mu(d)} \\&=\prod\limits_{g=1}^{\min(n, m)}f_g^{\sum\limits_{i=1}^{\lfloor\frac{n}{g}\rfloor}\sum\limits_{j=1}^{\lfloor\frac{m}{g}\rfloor}\sum\limits_{d}[d|i][d|j]\mu(d)} \\&=\prod\limits_{g=1}^{\min(n, m)}f_g^{\sum\limits_{d}\mu(d)\sum\limits_{i=1}^{\lfloor\frac{n}{g}\rfloor}[d|i]\sum\limits_{j=1}^{\lfloor\frac{m}{g}\rfloor}[d|j]} \\&=\prod\limits_{g=1}^{\min(n, m)}f_g^{\sum\limits_{d}\mu(d)\lfloor\frac{n}{gd}\rfloor\lfloor\frac{m}{gd}\rfloor} \\&=\prod\limits_{g=1}^{\min(n, m)}f_g^{\sum\limits_{g|T}\mu(\frac{T}{g})\lfloor\frac{n}{T}\rfloor\lfloor\frac{m}{T}\rfloor}&(\texttt{代换 }T=gd) \\&=\prod\limits_{T}\prod\limits_{g|T}^{\min(n, m)}f_g^{\mu(\frac{T}{g})\lfloor\frac{n}{T}\rfloor\lfloor\frac{m}{T}\rfloor} \end{aligned} \]

设 \(\mathbf{F}(T)=\prod\limits_{g|T}f_g^{\mu(\frac{T}{g})}\)

\(\therefore\texttt{ 原式}=\prod\limits_{T=1}^{\min(n, m)}\mathbf{F}(T)^{\lfloor\frac{n}{T}\rfloor\lfloor\frac{m}{T}\rfloor}\)

\(\mathbf{F}(T)\) 进行 \(\Theta(n\log n)\) 预处理前缀积

其余部分用数论分块 \(\Theta(\sqrt{n})\) 计算

代码

const int N = 1e6 + 7, P = 1e9 + 7;

inline int64 fpow(int64 a, int64 b) {
    int64 ret = 1;
    while (b) {
        if (b & 1) ret = ret * a % P;
        a = a * a % P;
        b >>= 1;
    }
    return ret;
}
#define inv(x) fpow(x, P - 2)

namespace euler {
    bool IsntPrime[N];
    int prs[N], pcnt, mu[N];
    unsigned a[N];

    void init_prs(int n) {
        mu[1] = 1;
        for (int i = 2; i <= n; ++i) {
            if (!IsntPrime[i]) {
                prs[++pcnt] = i;
                mu[i] = -1;
            }
            for (int j = 1; j <= pcnt && prs[j] * i <= n; ++j) {
                IsntPrime[prs[j] * i] = true;
                if (i % prs[j] == 0) break;
                mu[prs[j] * i] = -mu[i];
            }
        }
    }
}

namespace fib {
    int f[N], invf[N];
    void init(int n) {
        invf[1] = f[1] = 1;
        for (int i = 2; i <= n; ++i) {
            f[i] = (f[i - 1] + f[i - 2]) % P;
            invf[i] = inv(f[i]);
        }
    }
}

namespace F {
    int64 f[N], sum[N];
    void init(int n) {
        for (int g = 0; g <= n; ++g) f[g] = 1;
        sum[0] = 1;
        for (int g = 1; g <= n; ++g) {
            for (int d = 1; d * g <= n; ++d) // T = d * g
                switch (euler::mu[d]) {
                    case 1: f[g * d] = f[g * d] * fib::f[g] % P; break;
                    case -1: f[g * d] = f[g * d] * fib::invf[g] % P; break;
                }
            sum[g] = sum[g - 1] * f[g] % P;
            // printf("f[%d] = %lld\n", g, f[g]);
        }
    }
    int64 prod(int l, int r) {
        return sum[r] * inv(sum[l - 1]) % P;
    }
}

signed main() {
    euler::init_prs(1e6);
    fib::init(1e6);
    F::init(1e6);
    int T, n, m;
    for (cin >> T; T--;) {
        cin >> n >> m;
        int64 ans = 1;
        for (int l = 1, r, bound = min(n, m); l <= bound; l = r + 1) {
            r = min(n / (n / l), m / (m / l));
            ans = ans * fpow(F::prod(l, r), int64(n / l) * (m / l) % (P - 1)) % P;
        }
        cout << ans << endl;
    }
    return 0;
}

标签:lfloor,frac,limits,题解,sum,rfloor,P3704,洛谷,prod
来源: https://www.cnblogs.com/hkxadpall/p/solution-luogu-P3704.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有