[BZOJ3309]DZY Loves Math

Posted by Dispwnl on August 26, 2018

题目

Description

对于正整数n,定义f(n)为n所含质因子的最大幂指数。例如f(1960)=f(2^3 × 5^1 × 7^2)=3, f(10007)=1, f(1)=0。

给定正整数a,b,求sigma(sigma(f(gcd(i,j)))) (i=1..a, j=1..b)。

Input

第一行一个数T,表示询问数。

接下来T行,每行两个数a,b,表示一个询问。

Output

对于每一个询问,输出一行一个非负整数作为回答。

Sample Input

4
7558588 9653114
6514903 4451211
7425644 1189442
6335198 4957

Sample Output

35793453939901
14225956593420
4332838845846
15400094813

HINT

【数据规模】

T<=10000

1<=a,b<=10^7

题解

题目要求$\sum_{i=1}^{a}\sum_{j=1}^{b}f(\gcd(i,j))$

可以化简成$\sum_{x=1}^{min(a,b)}\sum_{i=1}^{\left\lfloor\frac{a}{x}\right\rfloor}\sum_{j=1}^{\left\lfloor\frac{b}{x}\right\rfloor}[\gcd(i,j)==1]f(x)$

即$\sum_{x=1}^{min(a,b)}f(x)\sum_{i=1}^{\left\lfloor\frac{a}{x}\right\rfloor}\sum_{j=1}^{\left\lfloor\frac{b}{x}\right\rfloor}[\gcd(i,j)==1]$

先不管前面的,有没有发现后面部分很熟悉?

设$F(x)=\sum_{i=1}^{n}\sum_{j=1}^{m}[\gcd(i,j)==x],G(x)=\sum_{x\vert d}F(d)=\left\lfloor\frac{n}{x}\right\rfloor\left\lfloor\frac{m}{x}\right\rfloor$

莫比乌斯反演一下:$F(x)=\sum_{x\vert d}\mu(\frac{d}{x})G(d)$

这样式子就成了:$\sum_{x=1}^{min(a,b)}f(x)\sum_{i=1}^{min(\frac{a}{x},\frac{b}{x})}\mu(i)\left\lfloor\frac{a}{ix}\right\rfloor\left\lfloor\frac{b}{ix}\right\rfloor$

设$T=ix$,则有:$\sum_{T=1}^{min(a,b)}\left\lfloor\frac{a}{T}\right\rfloor\left\lfloor\frac{b}{T}\right\rfloor\sum_{x\vert T}f(x)\mu(\frac{T}{x})$

前面部分就是一个整除分块,后面怎么搞啊QAQ

由于$\mu$函数的性质,设$T$的质因子为$pm_1^{a_1},pm_2^{a_2},…,pm_n^{a_n}$

当$x$里某个$pm_i$的指数$<a_i-1$时,$\mu(\frac{T}{x})=0$

所以$x$有$2^n$种取值(对于每个$pm_i$,ta的指数取$a_i$或$a_i-1$)

假设最高幂次为$k$,即$f(x)=k$

所以$x$有2的指数种取值(比$k$幂次高的都为$a_i$,低的可以是$a_i$也可以是$a_i-1$)

对应着低于$k$次幂的质因子$\frac{T}{x}$里要么有要么没有

所以$\mu(\frac{T}{x})$取值为1或者-1(取决于质因子个数),而$f(x)$的取值一样,所以和为0

这种情况只适用于存在低于$k$次幂的质因子,也就是质因子指数不全相等

另一种情况是质因子指数全相等,即$T=pm_1^apm_2^a…pm_n^a$

还是那样,$\frac{T}{x}$里的质因数指数要么为1要么为0

所以当$x=pm_1^{a-1}pm_2^{a-1}…pm_n^{a-1}$的时候,即每一项的指数都为1

$f(x)=a-1$

而其他情况$x$里面必定有一个$pm_i^a$,所以$f(x)=a$

$\mu(\frac{T}{x})$取值还是为1或者-1

如果是上面的那种情况,一个$a$会对应着一个$-a$,一一抵消和为0

但是这里有且只有一种情况$f(x)=a-1$(设这种情况为$S$),所以和为$0+(a-1-a)\mu(pm_1pm_2…pm_n)$,如果$n$为奇数,$\mu(S)=-1$,原来与它抵消的情况质因子个数为偶数(即$n-1$),所以答案为1,反之答案为-1,所以最后答案为$(-1)^{(n+1)}$

关于这个的处理也很有意思,需要记录每个数去掉最小质因数后剩下的数和最小质因数的次幂,这样小的数先计算,大的数通过小的数计算,线筛中计算就行了

代码

# include<iostream>
# include<cstring>
# include<cstdio>
# include<algorithm>
# define LL long long
using namespace std;
const int MAX=1e7+1,MAXN=1e4+1;
int t,a,b,tot,maxn;
int ls[MAX],num[MAX],sum[MAX],pm[MAX];
int qu[MAXN][2];
bool use[MAX];
int main()
{
	scanf("%d",&t);
	for(int i=1;i<=t;++i)
	  scanf("%d%d",&qu[i][0],&qu[i][1]),maxn=max(maxn,max(qu[i][0],qu[i][1]));
	for(int i=2;i<=maxn;++i)
	  {
	  	if(!use[i]) pm[++tot]=i,ls[i]=sum[i]=num[i]=1;
	  	for(int j=1;j<=tot&&i*pm[j]<=maxn;++j)
	  	  {
	  	  	use[i*pm[j]]=1;
	  	  	if(i%pm[j]==0)
	  	  	{
	  	  		num[i*pm[j]]=num[i]+1,ls[i*pm[j]]=ls[i];
	  	  		if(ls[i*pm[j]]==1) sum[i*pm[j]]=1;
	  	  		else if(num[ls[i*pm[j]]]==num[i*pm[j]]) sum[i*pm[j]]=-sum[ls[i*pm[j]]];
	  	  		else sum[i*pm[j]]=0;
	  	  		break;
	  	  	}
	  	  	ls[i*pm[j]]=i,num[i*pm[j]]=1;
			if(num[i]==1) sum[i*pm[j]]=-sum[i];
			else sum[i*pm[j]]=0;
		  }
	  }
	for(int i=1;i<=maxn;++i)
	  sum[i]+=sum[i-1];
	int a=qu[1][0],b=qu[1][1];
	for(int i=1;i<=t;a=qu[++i][0],b=qu[i][1])
	  {
		if(a>b) swap(a,b);
		LL ans=0;
		for(int l=1,r;l<=a;l=r+1)
		  {
		  	int N=a/l,M=b/l;
		  	r=min(a/N,b/M),ans+=1ll*N*M*(sum[r]-sum[l-1]);
		  }
		printf("%lld\n",ans);
	  }
	return 0;
}