P2257 YY的GCD
题目
求:
\[\large \sum\limits_{k\ is\ prime}\sum\limits_{i=1}^n\sum\limits_{j=1}^m[\gcd(i,j)=k]
\]
分析
根据结论,那么直接把后半写成:
\[\large \sum\limits_{k\ is\ prime}\sum\limits_{k|d} \mu(\frac{d}{k}) \lfloor\dfrac nd\rfloor\lfloor \dfrac md\rfloor
\]
然后转为枚举 \(d\) :
\[\large \sum\limits_{d=1}^{\min(n,m)} \lfloor\dfrac nd\rfloor\lfloor \dfrac md\rfloor\sum\limits_{k\mid d,k\ is\ prime}\mu(\frac{d}{k})
\]
那么最后那个柿子可以通过一点小办法处理出来,然后前面就是整除分块。
后面那个可以这样做:考虑每一个质数 \(k\) ,对于 \(k\) 的倍数 \(T\) ,将它的值加上 $ \mu(\frac{T}{k})$
代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define ull unsigned long long
#define inc(x,y,mod) (((x)+(y))>=(mod)?(x)+(y)-(mod):(x)+(y))
#define dec(x,y,mod) ((x)-(y)<0?(x)-(y)+(mod):(x)-(y))
#define rep(i,x,y) for(int i=(x);i<=(y);i++)
#define dep(i,y,x) for(int i=(y);i>=(x);i--)
const int N=1e7+5,M=2e5+5,MOD=1e9+7;
int n,m,k;
int prime[N],mu[N],cnt,pre[N];
ll val[N],Ans;
bool isprime[N];
void GetPrimes(int v){
mu[1]=1;
for(int i=2;i<=v;i++){
if(!isprime[i]) prime[++cnt]=i,mu[i]=-1;
for(int j=1;j<=cnt&&prime[j]*i<=v;j++){
isprime[i*prime[j]]=true;
if(i%prime[j]==0) break;
mu[i*prime[j]]=-mu[i];
}
}
for(int i=1;i<=cnt;i++) for(int j=1;j*prime[i]<=v;j++) val[j*prime[i]]+=mu[j];
for(int i=1;i<=v;i++) val[i]+=val[i-1];
return ;
}
signed main(){
ios::sync_with_stdio(false);
GetPrimes(1e7);
int t;cin>>t;
while(t--){
cin>>n>>m;Ans=0;
if(n<m) swap(n,m);
for(int l=1,r;l<=m;l=r+1){
r=min(n/(n/l),m/(m/l));
Ans+=1ll*(val[r]-val[l-1])*(n/(l))*(m/(l));
}
cout<<Ans<<endl;
}
return 0;
}