[bzoj4816][Sdoi2017]数字表格

题目大意:有$T(T\leqslant 1000)$组数据,每组数据给你$n,m(1\leqslant n,m \leqslant 10^6)$,求出$\displaystyle\prod\limits_{i=1}^n \displaystyle\prod\limits_{j=1}^m F[(i,j)]$($F(i)$为$fibonacci$数列第$i$项)

题解:下文中假设$n \leqslant m$
$$
\def\dprod{\displaystyle\prod\limits}\\
\def\dsum{\displaystyle\sum\limits}\\
\dprod_{i=1}^n\dprod_{j=1}^m F[(i,j)]=\dprod_{d=1}^n F(d)^{\sum_{i=1}^n\sum_{j=1}^m [(i,j)==d]}\\
令g(p)=\dsum_{i=1}^n\dsum_{j=1}^m [(i,j)==p]\\
\begin{align*}
令G(p)&=\dsum_{p|k}g(k)\\
    &=\dsum_{p|k}\dsum_{i=1}^n\dsum_{j=1}^m [(i,j)==k]\\
    &=\dsum_{i=1}^n\dsum_{j=1}^m [p|(i,j)]\\
    &=\left\lfloor\dfrac{n}{p}\right\rfloor\cdot\left\lfloor\dfrac{m}{p}\right\rfloor
\end{align*}\\
$$

$$
\def\dsum{\displaystyle\sum\limits}\\
莫比乌斯反演得:\\
\begin{align*}
g(p)&=\dsum_{p|k}\mu\big(\dfrac{k}{p}\big)G(p)\\
    &=\dsum_{p|k}\mu\big(\dfrac{k}{p}\big)\left\lfloor\dfrac{n}{p}\right\rfloor\cdot\left\lfloor\dfrac{m}{p}\right\rfloor\\
    &=\dsum_{i=1}^n\mu(i)\left\lfloor\dfrac{n}{i\cdot p}\right\rfloor\cdot\left\lfloor\dfrac{m}{i\cdot p}\right\rfloor
\end{align*}
$$

$$
\def\dprod{\displaystyle\prod\limits}\\
\def\dsum{\displaystyle\sum\limits}\\
\begin{align*}
\dprod_{i=1}^n\dprod_{j=m}^m F[(i,j)]&=\dprod_{d=1}^n F(d)^{\sum_{i=1}^n\sum_{j=1}^m [(i,j)==d]}\\
        &=\dprod_{d=1}^nF(d)^{g(d)}\\
        &=\dprod_{d=1}^nF(d)^{\sum_{i=1}^n\mu(i)\lfloor\frac{n}{i p}\rfloor\cdot\lfloor\frac{m}{i p}\rfloor}\\
        &=\dprod_{d=1}^n\dprod_{d|k}F(d)^{\mu\big(\dfrac{k}{d}\big)\big\lfloor\dfrac{n}{k}\big\rfloor\big\lfloor\dfrac{m}{k}\big\rfloor}\\
        &=\dprod_{k=1}^n\bigg(\dprod_{d|k}F(d)^{\mu\big(\dfrac{k}{d}\big)}\bigg)^{\big\lfloor\dfrac{n}{k}\big\rfloor\big\lfloor\dfrac{m}{k}\big\rfloor}\\
\end{align*}\\
$$

$$
\def\dprod{\displaystyle\prod\limits}\\
令s[k]=\dprod_{d|k}F(d)^{\mu\big(\dfrac{k}{d}\big)}\\
预处理出s,然后整除分块就行了
$$

卡点:



C++ Code:

#include <cstdio>
#include <cstring>
#define maxn 1000010
using namespace std;
const int mod = 1000000007;
int F[maxn], invF[maxn], s[maxn], invs[maxn];
int plist[maxn], miu[maxn], ptot;
bool isp[maxn];
int pw(int base, int p) {
    base %= mod, p %= mod - 1;
    int ans = 1;
    for (; p; p >>= 1, base = 1ll * base * base % mod)
        if (p & 1) ans = 1ll * ans * base % mod;
    return ans;
}
int inv(int a) {
    return pw(a, mod - 2);
}
void sieve(int n) {
    invs[0] = s[0] = s[1] = 1;
    F[0] = 0; invF[1] = F[1] = miu[1] = 1;
    for (int i = 2; i < n; i++) {
        s[i] = 1;
        F[i] = (F[i - 1] + F[i - 2]) % mod;
        invF[i] = inv(F[i]);
        if(!isp[i]) plist[ptot++] = i, miu[i] = -1;
        for (int j = 0; j < ptot && i * plist[j] < n; j++) {
            int tmp = i * plist[j];
            isp[tmp] = true;
            if (i % plist[j] == 0) {
                miu[tmp] = 0;
                break;
            }
            miu[tmp] = -miu[i];
        }
    }
    for (int i = 1; i < n; i++) {
        for (int j = 1, k = i; k < n; j++, k += i) {
            if (miu[j] == 1) s[k] = 1ll * s[k] * F[i] % mod;
            if (miu[j] == -1) s[k] = 1ll * s[k] * invF[i] % mod;
        }
    }
    for (int i = 1; i < n; i++) {
        s[i] = 1ll * s[i] * s[i - 1] % mod;
        invs[i] = inv(s[i]);
    }
}
inline int min(int a, int b) {return a < b ? a : b;}
int solve(int n, int m) {
    int tmp = min(n, m), ans = 1, j;
    for (int i = 1; i <= tmp; i = j + 1) {
        j = min(n / (n / i), m / (m / i));
        ans = 1ll * ans * pw(1ll * s[j] * invs[i - 1] % mod, 1ll * (n / i) * (m / i) % (mod - 1)) % mod;
    }
    return ans;
}
int Tim, n, m;
int main() {
    sieve(maxn);
    scanf("%d", &Tim);
    while (Tim --> 0) {
        scanf("%d%d", &n, &m);
        printf("%d\n", solve(n, m));
    }
    return 0;
}

 




posted @ 2018-08-23 10:52  Memory_of_winter  阅读(164)  评论(0编辑  收藏  举报