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;
}

转载于:https://www.cnblogs.com/nervendnig/p/9485035.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值