正题
P3455
题目大意
有T组询问,每组询问给出n,m,c,求∑i=1n∑j=1m[(i,j)=c]\sum_{i=1}^{n}\sum_{j=1}^{m}[(i,j)=c]i=1∑nj=1∑m[(i,j)=c]
解题思路
可以先对n,m除c这样就使得求出的数都有c的因子,得到式子如下
∑i=1n∑j=1m[(i,j)=1]∑i=1n∑j=1m∑d∣i,d∣jμ(d)∑d=1min(n,m)μ(d)×⌊nd⌋×⌊md⌋\sum_{i=1}^{n}\sum_{j=1}^{m}[(i,j)=1]\\ \sum_{i=1}^{n}\sum_{j=1}^{m}\sum_{d|i,d|j}\mu(d)\\ \sum_{d=1}^{min(n,m)}\mu(d)\times \left\lfloor\frac{n}{d}\right\rfloor\times \left\lfloor\frac{m}{d}\right\rfloor i=1∑nj=1∑m[(i,j)=1]i=1∑nj=1∑md∣i,d∣j∑μ(d)d=1∑min(n,m)μ(d)×⌊dn⌋×⌊dm⌋
然后整除分块求解
时间复杂度O(Tn)O(T\sqrt{n})O(Tn)
code
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define ll long long
#define N 50050
using namespace std;
int T,n,m,d,w,ans,mu[N],p[N],prime[N];
void work()
{p[1]=1;mu[1]=1;for(int i=2;i<=50000;++i){if(!p[i]){prime[++w]=i;mu[i]=-1;}for(int j=1;j<=w&&i*prime[j]<=50000;++j){p[i*prime[j]]=1;if(i%prime[j]==0){mu[i*prime[j]]=0;break;}else mu[i*prime[j]]=-mu[i];}}for(int i=2;i<=50000;++i)mu[i]+=mu[i-1];return;
}
int main()
{work();scanf("%d",&T);while(T--){scanf("%d%d%d",&n,&m,&d);n/=d;m/=d;ans=0;for(int l=1,r=0;l<=min(n,m);l=r+1){r=min(n/(n/l),m/(m/l));ans+=(mu[r]-mu[l-1])*(n/l)*(m/l);}printf("%d\n",ans);}return 0;
}