P5176 公约数
题意:求

对 \(10^9+7\) 取模的值。
这东西一看就十分炸裂,如何化简?
首先有恒等式:
它可以通过唯一分解定理证明。
然后很多东西都可以约分了,最后式子化为:
接下来把它分成三个结构一样的和式,如下:
现在我们来看第一个和式。可以发现 \(p\) 仅作贡献次数的作用,所以把它提到前面:
仅看 \(p\) 后面那个式子,不妨设 \(n\le m\),然后枚举因数:
将 \([x=1]\) 转化为 \(\underset{d|x}{\sum}\mu(d)\),有:
此处 \(i,j\) 和上文中 \(p\) 的意义一致,可以类似转化:
令 \(T=dk\),则有:
设 \(f(n)=\underset{d|n}{\sum}d^2\mu\left(\frac{n}{d}\right)\),则上式可写作:
可以发现这就是一个整除分块的形式,如果可以计算出 \(f(n)\) 的前缀和,就可以以 \(\mathcal O(\sqrt{n})\) 的时间复杂度内解决单次询问。所以问题转化到了如何快速求出 \(f(n)\)。
可以直观看出 \(f=g*\mu\),其中 \(g(n)=n^2\)。这告诉我们它是一个积性函数,提示着我们可以像线性筛一样把它递推计算出来。
线性筛中要考虑到的四条性质,此处一一列举:
- \(f(1)=1\)。
- \(f(p)=p^2-1\),其中 \(p\) 是质数。
- \(f(xy)=f(x)f(y)\),其中 \(x\perp y\)。
- \(f(px)=p^2f(x)\),其中 \(p\) 是 \(x\) 的最小质因子。
此处写一下第四条的证明:
其中 \(p\) 是质数,\(k\) 是任意大于等于二的整数。可知 \(d=p^l\),其中 \(0\le l\le k\)。由于 \(\mu\) 的定义,这个和式中真正有贡献的仅有两项:
观察可知 \(f\left(p^k\right)=p^2f\left(p^{k-1}\right)\),在推广一下即可得出第四条。
最后设上面那个式子为 \(h(n,m)\),则本题答案为:
然后这道题就做完了。代码:
#include<bits/stdc++.h>
using namespace std;
const int N=2e7+5,P=1e9+7;
typedef long long ll;
int p[N/7],pind;
bool nonp[N];
int f[N];
void ini(int n=2e7){
	nonp[1]=true,f[1]=1;
	for(int i=2;i<=n;i++){
		if(!nonp[i])p[++pind]=i,f[i]=((ll)i*i-1)%P;
		for(int j=1;j<=pind&&i*p[j]<=n;j++){
			nonp[i*p[j]]=true;
			if(!(i%p[j])){
				f[i*p[j]]=(ll)f[i]*p[j]%P*p[j]%P;
				break;
			}
			f[i*p[j]]=(ll)f[i]*f[p[j]]%P;
		}
	}
	for(int i=1;i<=n;i++){
		f[i]+=f[i-1];
		if(f[i]>=P)f[i]-=P;
	}
}
int calc(int n,int m){
	int ans=0;
	if(n>m)swap(n,m);
	for(int l=1,r;l<=n;l=r+1){
		r=min(n/(n/l),m/(m/l));
		ans=(ans+(ll)(n/l)*(m/l)%P*(f[r]-f[l-1])%P)%P;
	}
	return ans;
}
int main(){
	
	ios::sync_with_stdio(0),cin.tie(0);
	ini();
	int t;cin>>t;
	while(t--){
		int n,m,p;cin>>n>>m>>p;
		int ans=((ll)p*calc(n,m)%P+(ll)n*calc(m,p)%P+(ll)m*calc(n,p)%P)%P;
		cout<<(ans+P)%P<<"\n";
	}
	
	return 0;
}

 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号