BZOJ3994:[SDOI2015]约数个数和——题解

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ3994:[SDOI2015]约数个数和——题解相关的知识,希望对你有一定的参考价值。

http://www.lydsy.com/JudgeOnline/problem.php?id=3994

https://www.luogu.org/problemnew/show/P3327#sub

参考:https://blog.csdn.net/zmoiynlp/article/details/45176129

(他的公式好像最后一点有些问题)

请先锻炼好抗打击能力再做这道题,可以看我的模板:数论函数 & 莫比乌斯反演

我们有\\(d(ij)=\\sum_{k|i}\\sum_{l|j}[gcd(k,l)==1]\\)

(感性证明很简单,于是就不证了)

(这个是本题第一难的地方,信息数学竞赛

\\(\\sum_{i=1}^n\\sum_{j=1}^md(ij)\\)

\\(=\\sum_{i=1}^n\\sum_{j=1}^m\\sum_{k|i}\\sum_{l|j}[gcd(k,l)=1]\\)

\\(=\\sum_{k=1}^n\\sum_{l=1}^m\\lfloor\\frac{n}{k}\\rfloor\\lfloor\\frac{m}{l}\\rfloor[gcd(k,l)=1]\\)(跳了步,希望大家看得懂)

\\(=\\)套路(实则是跳步)

\\(=\\sum_{d=1}^{min(n,m)}\\mu(d)\\sum_{k=1}^{n}\\sum_{l=1}^{m}\\lfloor\\frac{n}{k}\\rfloor\\lfloor\\frac{m}{l}\\rfloor[k|d][l|d]\\)

\\(=\\sum_{d=1}^{min(n,m)}\\mu(d)\\sum_{k=1}^{\\lfloor\\frac{n}{d}\\rfloor}\\sum_{l=1}^{\\lfloor\\frac{m}{d}\\rfloor}\\lfloor\\frac{n} {kd}\\rfloor\\lfloor\\frac{m}{ld}\\rfloor\\)

我们令\\(g(n)=\\sum_{i=1}^n\\lfloor\\frac{n}{i}\\rfloor\\)

我们的套路有\\(\\sum_{i=1}^n\\sum_{j=1}^n[i|j]=g(n)\\)

是的你没有看错这玩意就是约数函数的前缀和。

(如果你还没看出来的话,把两个sigma颠倒一下)

(这是本题第二难的地方,信息数学竞赛

于是预处理约数函数的前缀和。

(用到了算数基本定理的推导和约数函数是积性函数的性质,可见https://blog.csdn.net/ControlBear/article/details/77527115

(emmm……就算你全推出来了,这个不会也白搭,信息数学竞赛

(我为什么要去作死做信息数学竞赛题啊!)

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N=5e4+5;
inline int read(){int x;scanf("%d",&x);return x;}
ll su[N],miu[N],d[N],c[N];
int he[N];
void init(int n){
	int tot=0;
	miu[1]=d[1]=c[1]=1;
	for(int i=2;i<=n;i++){
		if(!he[i]){
			su[++tot]=i;
			miu[i]=-1;
			c[i]=1;d[i]=2;
		}
		for(int j=1;j<=tot;j++){
			if(i*su[j]>n)break;
			he[i*su[j]]=1;
			if(i%su[j]==0){
				miu[i*su[j]]=0;
				d[i*su[j]]=d[i]/(c[i]+1)*(c[i]+2);
				c[i*su[j]]=c[i]+1;
				break;
			}else{
				miu[i*su[j]]=miu[i]*miu[su[j]];
				d[i*su[j]]=d[i]*d[su[j]];
				c[i*su[j]]=1;	
			}
		}
	}
	for(int i=1;i<=n;i++){
		miu[i]+=miu[i-1];
		d[i]+=d[i-1];
	}
}
int main(){
	init(5e4);
	int t=read();
	while(t--){
		ll n=read(),m=read();
		ll ans=0;
		for(ll i=1,j;i<=min(n,m);i=j+1){
			j=min(n/(n/i),m/(m/i));
			ans+=(miu[j]-miu[i-1])*d[n/i]*d[m/i];
		}
		printf("%lld\\n",ans);
	}
    return 0;
}
+++++++++++++++++++++++++++++++++++++++++++

+本文作者:luyouqi233。               +

+欢迎访问我的博客:http://www.cnblogs.com/luyouqi233/+

+++++++++++++++++++++++++++++++++++++++++++

以上是关于BZOJ3994:[SDOI2015]约数个数和——题解的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ 3994: [SDOI2015]约数个数和

bzoj3994:[SDOI2015]约数个数和

bzoj3994: [SDOI2015]约数个数和(莫比乌斯反演+分块)

bzoj 3994: [SDOI2015]约数个数和

BZOJ_3994_[SDOI2015]约数个数和_莫比乌斯反演

Bzoj3994 [SDOI2015]约数个数和

(c)2006-2024 SYSTEM All Rights Reserved IT常识