莫比乌斯反演练习

前置知识

莫比乌斯函数:

μ ( 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=11k1

s ( n ) = ∑ d ∣ n μ ( d ) = [ n = 1 ] s(n)=\sum_{d|n} μ(d)=[n=1] s(n)=dnμ(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)=dnf(d)时,有 f ( n ) = ∑ d ∣ n μ ( d ) F ( n d ) f(n)=\sum_{d|n} μ(d) F(\frac{n}{d}) f(n)=dnμ(d)F(dn)

2、当 F ( n ) = ∑ n ∣ d f ( d ) F(n)=\sum_{n|d} f(d) F(n)=ndf(d)时,有 f ( n ) = ∑ n ∣ d μ ( d n ) F ( d ) f(n)=\sum_{n|d} μ(\frac{d}{n}) F(d) f(n)=ndμ(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=1xj=1y[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(a1,d)S(b,c1)+S(a1,c1)

那么本题转变为求 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=1xj=1y[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=1xj=1y[ngcd(i,j)]

F ( n ) = ∑ n ∣ d f ( d ) F(n)=\sum_{n|d} f(d) F(n)=ndf(d)满足第二种反演

f ( n ) = ∑ n ∣ d μ ( d n ) F ( d ) f(n)=\sum_{n|d} μ(\frac{d}{n}) F(d) f(n)=ndμ(nd)F(d)

d ∣ g c d ( i , j ) d|gcd(i,j) dgcd(i,j)

d ∣ i 且 d ∣ j d|i且d|j didj

即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)=dxdy

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)=ndμ(nd)dxdy

d ′ = d n d'=\frac{d}{n} d=nd d = d ′ ∗ n d=d'*n d=dn

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)dnxdny

d ′ > x n 或 d ′ > y n d'>\frac{x}{n}或d'>\frac{y}{n} d>nxd>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=1min(nx,ny)μ(d)dnxdny

令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是真的难敲。。。本来准备敲两题题解的,看到又是一大堆公式劝退了。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

第十页

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值