zoukankan      html  css  js  c++  java
  • BZOJ4816 数字表格

    4816: [Sdoi2017]数字表格

    Time Limit: 50 Sec  Memory Limit: 128 MB

    Description

    Doris刚刚学习了fibonacci数列。用f[i]表示数列的第i项,那么
    f[0]=0
    f[1]=1
    f[n]=f[n-1]+f[n-2],n>=2
    Doris用老师的超级计算机生成了一个n×m的表格,第i行第j列的格子中的数是f[gcd(i,j)],其中gcd(i,j)表示i,j的最大公约数。Doris的表格中共有n×m个数,她想知道这些数的乘积是多少。答案对10^9+7取模。

    Input

    有多组测试数据。

    第一个一个数T,表示数据组数。
    接下来T行,每行两个数n,m
    T<=1000,1<=n,m<=10^6

    Output

    输出T行,第i行的数是第i组数据的结果

    Sample Input

    3
    2 3
    4 5
    6 7

    Sample Output

    1
    6
    960

    题解

    这道题很好地延续了SDOI的优良传统,考了一道莫比乌斯反演以供娱乐。

    由于我们一眼发现了这是一道莫比乌斯反演水题,正如做所有的莫比乌斯反演一样,我们把要求的式子先写出来并推导

    egin{eqnarray*}
    ans & = & prod_{i}^{n}prod _{j}^{m}f( gcd(i,j) ) \
    & = & prod_{k}^{n}f(k) ^ {sum_{i}^{frac{n}{k}}sum_{j}^{frac{m}{k}}[gcd(i,j)=1]} \
    & = & prod_{k}^{n}f(k) ^ {sum_{i}^{frac{n}{k}}sum_{j}^{frac{m}{k}}sum_{xmid{i}&xmid{j}}~~mu(x)} \
    & = & prod_{k}^{n}prod_{x}^{frac{n}{k}}(f(k) ^ {mu(x)})^{frac{n}{kx}frac{m}{kx}}
    end{eqnarray*}

    为了能够把(f(k) ^ {mu(x)})提出来,显然,我们可以设(T=kx),(g(T)=prod_{kmid{T}}f(k) ^ {mu(frac{T}{k})})

    化简得到(ans = prod_{T}^{n}g(T)^{frac{n}{T}frac{m}{T}})

    求出$f$以及$f$的逆元,线性筛求$mu$,Dirichlet卷积求出$g$,然后计算$g$的前缀积$g'$以及$g'$的逆元

    查询使用大众喜闻乐见的分块,至此,我们切掉了这道水题。

    代码

    #include<bits/stdc++.h>
    using namespace std;
    template <class _T> inline void read(_T &_x) {
        int _t; bool flag = false;
        while ((_t = getchar()) != '-' && (_t < '0' || _t > '9')) ;
        if (_t == '-') _t = getchar(), flag = true; _x = _t - '0';
        while ((_t = getchar()) >= '0' && _t <= '9') _x = _x * 10 + _t - '0';
        if (flag) _x = -_x;
    }
    typedef long long LL;
    const int maxn = 1000010;
    const int mod = 1000000007;
    int f[maxn], f_re[maxn], mu[maxn], g[maxn], g_re[maxn];
    bool vis[maxn]; int prime[maxn / 10], pcnt;
    #define trans(x) ((int)((LL)x % mod))
    #define reg register
    inline void update(int &a, reg int b) {
        a = trans(a * b);
        if (a < 0) a += mod;
    }
    inline int qpower(int a, reg LL b) {
        int ret = 1;
        while (b) {
            if (b & 1) update(ret, a);
            update(a, a), b >>= 1;
        }
        return ret;
    }
    inline int calc(reg int a, reg int b) {
        if (b == 0) return 1;
        return b < 0 ? f_re[a] : f[a];
    }
    void init() {
        f[0] = 0, f[1] = f_re[1] = g[1] = mu[1] = 1;
        reg int i, j;
        for (i = 2; i < maxn; ++i) {
            f[i] = f[i - 1] + f[i - 2];
            if (f[i] >= mod) f[i] -= mod;
            f_re[i] = qpower(f[i], mod - 2);
        }
        for (i = 2; i < maxn; ++i) {
            g[i] = 1;
            if (!vis[i]) {
                prime[++pcnt] = i;
                mu[i] = -1;
            }
            for (j = 1; j <= pcnt && prime[j] * i < maxn; ++j) {
                vis[i * prime[j]] = true;
                if (i % prime[j] == 0) {
                    mu[i * prime[j]] = 0;
                    break;
                }
                mu[i * prime[j]] = -mu[i];
            }
        }
        for (i = 1; i * i < maxn; ++i) {
            update(g[i * i], calc(i, mu[i]));
            for (j = i + 1; i * j < maxn; ++j)
                update(g[i * j], trans(calc(i, mu[j]) * calc(j, mu[i])));
        }
        g[0] = g_re[0] = 1;
        for (i = 1; i < maxn; ++i) {
            update(g[i], g[i - 1]);
            g_re[i] = qpower(g[i], mod - 2);
        }
    }
    inline int query(reg int a, reg int b) {
        if (a > b) {int t = a; a = b, b = t; }
        int ret = 1;
        for (reg int i = 1, j, x, y; i <= a; i = j + 1) {
            x = a / i, y = b / i;
            j = min(a / x, b / y);
            update(ret, qpower(trans(g[j] * g_re[i - 1]), (LL)x * y));
        }
        return ret;
    }
    int main() {
        //freopen(".in", "r", stdin);
        //freopen(".out", "w", stdout);
        init();
        int T, a, b; read(T);
        while (T--) {
            read(a), read(b);
            printf("%d
    ", query(a, b));
        }
        return 0;
    }
    View Code
  • 相关阅读:
    python笔记
    React+router和react+redux使用过程的记录
    jQuery源码分析随笔
    安装nodejs+ionic+cordova环境心得
    win10系统Nodejs安装包总是失败原因
    silverlight中dialogresult和close
    安卓HTTP访问的两种方式
    安卓Activity跳转的几种方式
    Android开发Content Provider
    web.xml中filter的用法
  • 原文地址:https://www.cnblogs.com/akhpl/p/6730864.html
Copyright © 2011-2022 走看看