前置知识
莫比乌斯函数:
μ ( n ) = { 1 n = 1 ( − 1 ) k 任 意 质 因 子 指 数 为 1 , k 为 质 因 子 个 数 0 存 在 质 因 子 个 数 大 于 1 μ(n)=\left\{ \begin{array}{rcl} 1 & & {n=1}\\ (-1)^k & & 任意质因子指数为1,k为质因子个数\\ 0 & & 存在质因子个数大于1 \end{array} \right. μ(n)=⎩⎨⎧1(−1)k0n=1任意质因子指数为1,k为质因子个数存在质因子个数大于1
s ( n ) = ∑ d ∣ n μ ( d ) = [ n = 1 ] s(n)=\sum_{d|n} μ(d)=[n=1] s(n)=∑d∣nμ(d)=[n=1](当且仅当n=1时[n=1]为1,否则为0)
莫比乌斯反演:
存在两种反演:
1、当 F ( n ) = ∑ d ∣ n f ( d ) F(n)=\sum_{d|n} f(d) F(n)=∑d∣nf(d)时,有 f ( n ) = ∑ d ∣ n μ ( d ) F ( n d ) f(n)=\sum_{d|n} μ(d) F(\frac{n}{d}) f(n)=∑d∣nμ(d)F(dn)
2、当 F ( n ) = ∑ n ∣ d f ( d ) F(n)=\sum_{n|d} f(d) F(n)=∑n∣df(d)时,有 f ( n ) = ∑ n ∣ d μ ( d n ) F ( d ) f(n)=\sum_{n|d} μ(\frac{d}{n}) F(d) f(n)=∑n∣dμ(nd)F(d)
证就不证了,一大把证的比我好的,把结论写下来能拿来用就行。
例题
problem b
题目链接:https://www.acwing.com/problem/content/2704/
大意
对于给出的 n 个询问,每次求有多少个数对 (x,y),满足 a≤x≤b,c≤y≤d,且 gcd(x,y)=k
思路
求{(x,y)|a≤x≤b,c≤y≤d}内的满足条件的数对数量
令 S ( x , y ) = ∑ i = 1 x ∑ j = 1 y [ g c d ( i , j ) = k ] S(x,y)=∑_{i=1}^x∑_{j=1}^y[gcd(i,j)=k] S(x,y)=i=1∑xj=1∑y[gcd(i,j)=k]
则满足条件的数对数量为 S ( b , d ) − S ( a − 1 , d ) − S ( b , c − 1 ) + S ( a − 1 , c − 1 ) S(b,d)−S(a−1,d)−S(b,c−1)+S(a−1,c−1) S(b,d)−S(a−1,d)−S(b,c−1)+S(a−1,c−1)
那么本题转变为求 S ( x , y ) S(x,y) S(x,y)
我们可以构造两个函数:
f ( n ) = ∑ i = 1 x ∑ j = 1 y [ g c d ( i , j ) = n ] f(n)=∑_{i=1}^x∑_{j=1}^y[gcd(i,j)=n] f(n)=i=1∑xj=1∑y[gcd(i,j)=n]
F ( n ) = ∑ i = 1 x ∑ j = 1 y [ n ∣ g c d ( i , j ) ] F(n)=∑_{i=1}^x∑_{j=1}^y[n|gcd(i,j)] F(n)=i=1∑xj=1∑y[n∣gcd(i,j)]
且 F ( n ) = ∑ n ∣ d f ( d ) F(n)=\sum_{n|d} f(d) F(n)=n∣d∑f(d)满足第二种反演
则 f ( n ) = ∑ n ∣ d μ ( d n ) F ( d ) f(n)=\sum_{n|d} μ(\frac{d}{n}) F(d) f(n)=n∣d∑μ(nd)F(d)
∵ d ∣ g c d ( i , j ) d|gcd(i,j) d∣gcd(i,j)
∴ d ∣ i 且 d ∣ j d|i且d|j d∣i且d∣j
即F(d)内个数为[1,x]区间内n倍数的个数乘[1,y]区间内n倍数的个数
∴ F ( d ) = ⌊ x d ⌋ ⌊ y d ⌋ F(d)=\lfloor \frac{x}{d} \rfloor\lfloor \frac{y}{d} \rfloor F(d)=⌊dx⌋⌊dy⌋
∴ f ( n ) = ∑ n ∣ d μ ( d n ) ⌊ x d ⌋ ⌊ y d ⌋ f(n)=∑_{n|d}μ(\frac{d}{n})\lfloor \frac{x}{d} \rfloor\lfloor \frac{y}{d} \rfloor f(n)=n∣d∑μ(nd)⌊dx⌋⌊dy⌋
设 d ′ = d n d'=\frac{d}{n} d′=nd则 d = d ′ ∗ n d=d'*n d=d′∗n
则 f ( n ) = ∑ d ′ = 1 ∞ μ ( d ′ ) ⌊ x d ′ n ⌋ ⌊ y d ′ n ⌋ f(n)=∑_{d'=1}^∞μ(d')\lfloor \frac{x}{d'n} \rfloor\lfloor \frac{y}{d'n} \rfloor f(n)=d′=1∑∞μ(d′)⌊d′nx⌋⌊d′ny⌋
又 d ′ > x n 或 d ′ > y n d'>\frac{x}{n}或d'>\frac{y}{n} d′>nx或d′>ny后+0无意义
所以 f ( n ) = ∑ d ′ = 1 m i n ( x n , y n ) μ ( d ′ ) ⌊ x d ′ n ⌋ ⌊ y d ′ n ⌋ f(n)=∑_{d'=1}^{min(\frac{x}{n},\frac{y}{n})}μ(d')\lfloor \frac{x}{d'n} \rfloor\lfloor \frac{y}{d'n} \rfloor f(n)=d′=1∑min(nx,ny)μ(d′)⌊d′nx⌋⌊d′ny⌋
令n=k,则S(x,y)=f(k);
所以求出莫比乌斯函数的前缀和后整数分块求乘积即可(每次 后面两个向下取整式子值一定时提出来乘以这段范围的莫比乌斯值之和)
CODE
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<string>
#include<vector>
#include<stack>
#include<bitset>
#include<cstdlib>
#include<cmath>
#include<set>
#include<list>
#include<deque>
#include<map>
#include<queue>
using namespace std;
typedef long long ll;
const int N=1e5+7;
const ll mod=1e9+7;
const ll maxn=5e4;
int prime[maxn+7];
int vis[maxn+7];
int mobius[maxn+7];
int sum[maxn+7];
int n,k;
int a,b,c,d;
void get_mobius()
{
mobius[1]=1;
for(int i=2;i<=maxn;i++)
{
if(!vis[i])
{
prime[++prime[0]]=i;
mobius[i]=-1;
}
for(int j=1;j<=prime[0]&&i*prime[j]<=maxn;j++)
{
vis[i*prime[j]]=1;
if(i%prime[j]==0)
{
mobius[i*prime[j]]=0;
break;
}
mobius[i*prime[j]]=-mobius[i];
}
}
for(int i=1;i<=maxn;i++)
{
sum[i]=sum[i-1]+mobius[i];
}
}
int solve(int x,int y)
{
ll ans=0;
for(int l=1,r;l<=min(x/k,y/k);l=r+1)
{
r=min(x/(x/l),y/(y/l));
ans+=(sum[r]-sum[l-1])*(x/k/r)*(y/k/r);
}
return ans;
}
int main()
{
ios::sync_with_stdio(0);
cin>>n;
get_mobius();
while(n--)
{
cin>>a>>b>>c>>d>>k;
cout<<solve(b,d)-solve(a-1,d)-solve(d,c-1)+solve(a-1,c-1)<<endl;
}
return 0;
}
LaTeX是真的难敲。。。本来准备敲两题题解的,看到又是一大堆公式劝退了。