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

浙公网安备 33010602011771号