最近在其他地方写文章,为了证明我没咕,把最近写的转到 $Mina$ 上来吧。

文章或许有纰漏,希望大神可以指出 $QwQ$ 。那么进入正题吧。

很显然是让我们求出下式:

$$ans=\sum_{i=1}^{A}\sum_{j=1}^{B}[gcd(i,j)=K]$$

根据性质可以得到:

$$ans=\sum_{i=1}^{\lfloor\frac{A}{K}\rfloor}\sum_{j=1}^{\lfloor\frac{B}{K}\rfloor}[gcd(i,j)=1]$$

我们设两个函数:

  • 函数 $f$,$f(x)$ 表示 $\sum_{i=1}^{\lfloor\frac{A}{K}\rfloor}\sum_{j=1}^{\lfloor\frac{B}{K}\rfloor}[gcd(i,j)=x]$
  • 函数 $g$ ,$g(x)$ 表示 $\sum_{i=1}^{\lfloor\frac{A}{K}\rfloor}\sum_{j=1}^{\lfloor\frac{B}{K}\rfloor}[x|gcd(i,j)]$

我们可以得到:

$$g(x)=\sum_{x|d} f(d)$$

这是莫比乌斯反演的第二个形式:

$$g(n)=\sum_{n|d} f(d) \ \Rightarrow \ f(n)=\sum_{n|d}g(d) \cdot \mu(\frac{d}{n})$$

于是:

$$g(x)=\sum_{x|d} f(x) \ \Rightarrow \ f(x)=\sum_{x|d}g(x) \cdot \mu(\frac{d}{x})$$

$$=g(x)=\sum_{x|d} f(x) \ \Rightarrow \ f(x)=\sum_{x|d}g(\frac{d}{x}) \cdot \mu(x)$$

设 $n=\lfloor\frac{A}{K}\rfloor\ ,\ m=\lfloor\frac{B}{K}\rfloor$

那么:

$$g(x)=\sum_{i=1}^{n}\sum_{i=1}^{m} [x|gcd(i,j)]=\sum_{i=1}^{\lfloor\frac{n}{K}\rfloor}\sum_{j=1}^{\lfloor\frac{m}{K}\rfloor}[1|gcd(i,j)]$$

$$=\sum_{i=1}^{\lfloor\frac{n}{K}\rfloor}\sum_{j=1}^{\lfloor\frac{m}{K}\rfloor}[1|gcd(i,j)]=\lfloor\frac{A}{K}\rfloor \times\lfloor\frac{B}{K}\rfloor$$

$$ans=f(1)$$

$$f(1)=\sum_{i=1}^{n}\mu(i)\cdot g(i)=\sum_{i=1}^{n}\mu(i)\cdot\lfloor\frac{A}{K}\rfloor \cdot\lfloor\frac{B}{K}\rfloor$$

这个式子是 $O(n)$ 的。

发现 $\lfloor\frac{A}{K}\rfloor \times\lfloor\frac{B}{K}\rfloor$ 可以整除分块,于是我们便可以做到 $O(\sqrt{n})$

Code:

#include<cmath>
#include<cstdio>
#include<iostream>
#include<algorithm>

const int N=1e5+2;
const int inf=1e9+9;

int T,cnt;
int prime[N],mui[N],vis[N];
long long sum[N];

inline int _Pre_mui(){
    mui[1]=1;
    for(int i=2;i<=N;++i){
        if(!vis[i])prime[++cnt]=i,mui[i]=-1;
        for(int j=1;j<=cnt;++j){
            if(i*prime[j]>=N)break;
            vis[i*prime[j]]=1;
            if(!(i%prime[j])){mui[i*prime[j]]=0;break;}
            else mui[i*prime[j]]=-mui[i];
        }
    }for(int i=1;i<=N;++i)sum[i]=sum[i-1]+mui[i];
    return 0;
}

#define min(x,y) ((x)<(y)?(x):(y))

inline void solve(int n,int m,int k){
    long long ans=0;
    n/=k,m/=k;
    int lim=min(n,m);
    for(int i=1;i<=lim;){
        long long j=min(n/(n/i),m/(m/i));
        ans+=1ll*(sum[j]-sum[i-1])*(n/i)*(m/i);n
        i=j+1;
    }printf("%lld\n",ans);
    return;
}

int main(){
    _Pre_mui();
    scanf("%d",&T);
    while(T--){
        int n,m,k;
        scanf("%d%d%d",&n,&m,&k);
        solve(n,m,k);
    }return 0;  
}

所以就没了。

分类: 文章

Qiuly

QAQ

0 条评论

发表回复

Avatar placeholder

您的电子邮箱地址不会被公开。 必填项已用*标注