【LGP5176】公约数

题目

老年选手啥都不想推只能搞个杜教筛了

这个式子长得好吓人啊,所以我们唯一分解之后来考虑这道题

(i,j,k)分别是(p^a,p^b,p^c),至于到底谁是谁并不重要,我们不妨假设(aleq bleq c)

那么(gcd(i imes j,j imes k,k imes i)=min{p^{a+b},p^{a+c},p^{b+c}}=p^{a+b})

(gcd(i,j,k)=min{p^a,p^b,p^c}=p^a)

也就是前面两个柿子乘起来是(p^{2a+b})

我们把后面的柿子分母通分

[frac{(i,j)^2+(j,k)^2+(k,i)^2}{(i,j)(j,k)(k,i)} ]

我们发现分母上还是等于(p^{2a+b}),因为(p^a)跟另外两个组合得到的(gcd)都是(p^a)(p^b)(p^{c})(gcd)(p^b),所以分母上是(p^{2a+b})

和外面一约分,没了

显然唯一分解之后各个质数次幂是相互独立的,于是我们现在可以得出结论,我们要求的就是

[sum_{i=1}^nsum_{j=1}^msum_{k=1}^p(i,j)^2+(j,k)^2+(k,i)^2 ]

显然可以拆成

[p imes sum_{i=1}^nsum_{j=1}^m(i,j)^2+n imes sum_{j=1}^msum_{k=1}^p(j,k)^2+m imes sum_{i=1}^nsum_{k=1}^p(k,i)^2 ]

套路反演我们可以得到我们要求的东西实际上是

[sum_{i=1}^nleft lfloor frac{n}{i} ight floorleft lfloor frac{m}{i} ight floorsum_{d|i}mu(frac{i}{d})d^2 ]

后面的东西线筛也很好推,但是老年选手并不想动脑子了

发现后面的柿子是(id^2 imes mu),我们直接杜教筛卷上(1)就变成(id^2)了,(id^2)的前缀和自然是(frac{n(n+1)(2n+1)}{6})

这样是(O(n^{frac{3}{4}}))的,但是我们暴力调合级数处理一些,就能跑的很快了

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define re register
#define LL long long
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
inline int read() {
	char c=getchar();int x=0;while(c<'0'||c>'9') c=getchar();
	while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+c-48,c=getchar();return x;
}
int T;
const int I6=166666668;
const int mod=1e9+7;
const int maxn=1e6+1;
int p[maxn>>1],is[maxn],mu[maxn];
int f[20000005],vis[20000005];
inline int calc(int x) {return 1ll*x*(x+1)%mod*(x+x+1)%mod*I6%mod;}
inline int solve(int x) {
	if(vis[x]) return f[x];
	vis[x]=1;int ans=calc(x);
	for(re int l=2,r;l<=x;l=r+1) {
		r=x/(x/l);
		ans=(ans-1ll*solve(x/l)*(r-l+1)%mod+mod)%mod;
	}
	return f[x]=ans;
}
inline int work(int n,int m) {
	if(n>m) std::swap(n,m);
	int ans=0;
	for(re int l=1,r;l<=n;l=r+1) {
		r=min(n/(n/l),m/(m/l));
		ans=(ans+1ll*(n/l)*(m/l)%mod*(solve(r)-solve(l-1)+mod)%mod)%mod;
	}
	return ans;
}
int main() {
	T=read();is[1]=mu[1]=1;
	for(re int i=2;i<maxn;i++) {
		if(!is[i]) p[++p[0]]=i,mu[i]=-1;
		for(re int j=1;j<=p[0]&&p[j]*i<maxn;j++) {
			is[p[j]*i]=1;if(i%p[j]==0) break;mu[p[j]*i]=-1*mu[i];
		}
	}
	for(re int i=1;i<maxn;i++)
		for(re int j=i;j<maxn;j+=i) {
			if(!mu[j/i]) continue;
			if(mu[j/i]<0) f[j]=(f[j]-1ll*i*i%mod+mod)%mod;
				else f[j]=(f[j]+1ll*i*i)%mod;
		}
	for(re int i=1;i<maxn;i++)
		vis[i]=1,f[i]=(f[i]+f[i-1])%mod;
	while(T--) {
		int n=read(),m=read(),p=read();
		int tmp=1ll*work(n,m)*p%mod+1ll*work(m,p)*n%mod;tmp%=mod;
		tmp=(tmp+1ll*work(n,p)*m%mod)%mod;
		printf("%d
",tmp%mod);
	}
}
原文地址:https://www.cnblogs.com/asuldb/p/10777649.html