BZOJ 1101 Zap 莫比乌斯反演
https://www.lydsy.com/JudgeOnline/problem.php?id=1101
题意:
求$$\sum^a_{i=1} \sum^b_{j=1} [gcd(i,j)=k]$$
题解:
莫比乌斯反演裸题....$$\sum^a_{i=1} \sum^b_{j=1} [gcd(i,j)=k]$$
首先考虑到,原答案$$= \sum^{a/k}_{i=1} \sum^{b/k}_{j=1} [gcd(i,j)=1]$$
然后做一次反演:$$[gcd(i,j)=1] = \sum_{d|gcd(i,j)} μ(d)$$
然后换求和指标,记$a'=a/k , b'=b/k$ 得到:
然后用整除分块的方式降低求和复杂度就行....
#include <bits/stdc++.h> #define ll long long #define usd unsigned #define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0) #define rep(ii,a,b) for(int ii=a;ii<=b;ii++) #define per(ii,a,b) for(int ii=b;ii>=a;ii--) #define show(x) cout<<#x<<"="<<x<<endl #define show2(x,y) cout<<#x<<"="<<x<<" "<<#y<<"="<<y<<endl #define show3(x,y,z) cout<<#x<<"="<<x<<" "<<#y<<"="<<y<<" "<<#z<<"="<<z<<endl #define show4(w,x,y,z) cout<<#w<<"="<<w<<" "<<#x<<"="<<x<<" "<<#y<<"="<<y<<" "<<#z<<"="<<z<<endl #define showa(a,b) cout<<#a<<'['<<b<<"]="<<a[b]<<endl #define pii pair<int,int> using namespace std; const int maxn=5e4+10; const int maxm=2e6+10; const int INF=0x3f3f3f3f; const int mod=1e9+7; //head int casn,n,m,k; int num[maxn]; ll ans; int mu[maxn],prime[maxn],sum[maxn]; bool isp[maxn]; int nump; void getmu(){ mu[1]=1,nump=0; int n=maxn-10; rep(i,2,n){ if(!isp[i]) prime[++nump]=i,mu[i]=-1; for(int j=1;j<=nump&&prime[j]*i<=n;j++){ isp[i*prime[j]]=1; if(i%prime[j]==0) mu[i*prime[j]]=0,j=nump+10; else mu[i*prime[j]]=-mu[i]; } } rep(i,1,n){ sum[i]=sum[i-1]+mu[i]; } } #define tpyeinput int inline char nc() {static char buf[1000000],*p1=buf,*p2=buf;return p1==p2&&(p2=(p1=buf)+fread(buf,1,1000000,stdin),p1==p2)?EOF:*p1++;} inline void read(tpyeinput &sum) {char ch=nc();sum=0;while(!(ch>='0'&&ch<='9')) ch=nc();while(ch>='0'&&ch<='9') sum=(sum<<3)+(sum<<1)+(ch-48),ch=nc();} inline void read(tpyeinput &num1,tpyeinput &num2){read(num1);read(num2);} inline void read(tpyeinput &num1,tpyeinput &num2,tpyeinput &num3){read(num1);read(num2);read(num3);} inline void read(tpyeinput &num1,tpyeinput &num2,tpyeinput &num3,tpyeinput &num4){read(num1);read(num2);read(num3);read(num4);} int main(){ //#define test #ifdef test freopen("in.txt","r",stdin);freopen("out.txt","w",stdout); long long _begin_time = clock(); #endif getmu(); read(casn); while(casn--){ int a,b,c; read(a,b,c); a/=c,b/=c; if(a>b) swap(a,b); int ans=0,pos=0; for(int i=1;i<=a;i=pos+1){ pos=min(a/(a/i),b/(b/i)); ans+=(sum[pos]-sum[i-1])*(a/i)*(b/i); } printf("%d\n",ans); } #ifdef test long long _end_time = clock(); cerr << "time = " << _end_time - _begin_time << " ms\n"; fclose(stdin);fclose(stdout);system("out.txt"); #endif return 0; }