莫比乌斯反演
\(\color{red}{f(n)=\sum\limits_{d|n}}g(d) \Leftrightarrow g(n)=\sum\limits_{d|n}\mu(d)f(\dfrac{n}{d})\)
例题:P3704 [SDOI2017]数字表格
题意:给出 \(n,m\),求 \(\prod\limits^n_{i=1}\prod\limits^m_{j=1}f(gcd(i,j))\)
\(f(k)\) 表示第 \(k\) 项斐波那契数。数据 \(n,m\le 10^6,T=10^3,P=10^9+7\)
推导:
最终得出的式子:\(\prod^n_{T=1}(\prod^n_{d=1}f(d)^{\mu(\dfrac{T}{d})})^{\lfloor\dfrac{n}{T}\rfloor\lfloor\dfrac{m}{T}\rfloor}\)
令 \(F(T)=\prod\limits^n_{d=1}f(d)^{\mu(\dfrac{T}{d})}\)
\(\prod\limits^n_{T=1}F(T)^{\left\lfloor\dfrac{n}{T}\right\rfloor\left\lfloor\dfrac{m}{T}\right\rfloor}\)
那么这个式子处理起来也比较困难,对于 \(\mu(\dfrac{T}{d})\) 可能出现 \(-1\) 所以需要预处理逆元;对于 \(\left\lfloor\dfrac{n}{T}\right\rfloor\left\lfloor\dfrac{m}{T}\right\rfloor\) 这两个东西直接数论分块加快速幂;数列递推就好;单次循环的乘积,由于 \(n\) 不大,直接枚举就好;双次循环的乘积需要预处理前缀积,小心逆元!
#include <iostream>
#include <cstdio>
#include <cstdlib>
using namespace std;
#define P 1000000007
#define N 1000010
int mu[N], p[N], vis[N], cnt;
int f[N], g[N], F[N];
// f是斐波那契数列
int qpow(int a, int b)
{
int res = 1;
while (b)
{
if (b & 1)
res = 1ll * res * a % P;
a = 1ll * a * a % P;
b >>= 1;
}
return res;
}
void init()
{
mu[1] = 1;
for (int i = 2; i < N; ++i)
{
if (!vis[i])
p[++cnt] = i, mu[i] = -1;
for (int j = 1; i * p[j] < N; ++j)
{
vis[i * p[j]] = 1;
if (i % p[j] == 0)
break;
mu[i * p[j]] = -mu[i];
}
}
f[1] = g[1] = F[0] = F[1] = 1;
for (int i = 2; i < N; ++i)
{
f[i] = (f[i - 1] + f[i - 2]) % P;// 预处理fib
g[i] = qpow(f[i], P - 2);// 逆元
F[i] = 1;
}
for (int i = 1; i < N; ++i)
for (int j = i; j < N; j += i)
if (mu[j / i])
F[j] = 1ll * F[j] * (mu[j / i] == 1 ? f[i] : g[i]) % P;
for (int i = 2; i < N; ++i)
F[i] = 1ll * F[i] * F[i - 1] % P; // 前缀积
}
int calc(int n, int m)
{
if (n > m)
swap(n, m);// 推理是建立在n<m上的,理当交换位置
int r, s, ans = 1;
for (int l = 1; l <= n; l = r + 1)
{
r = min(n / (n / l), m / (m / l));
s = 1ll * F[r] * qpow(F[l - 1], P - 2) % P; // 区间积
ans = 1ll * ans * qpow(s, 1ll * (n / l) * (m / l) % (P - 1)) % P;
}
return ans;
}
int main()
{
init();
int T, n, m;
scanf("%d", &T);
while (T--)
{
scanf("%d%d", &n, &m);
printf("%d\n", calc(n, m));
}
}
这是我学会的第一道黑题,虽说是课上讲的,但是真理解了,在此纪念下。
标签:lfloor,limits,int,dfrac,P3704,mu,反演,SDOI2017,prod From: https://www.cnblogs.com/CYLSY/p/17023398.html