BZOJ3309: DZY Loves Math

BZOJ3309: DZY Loves Math

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


题解Here!

 

这。。。懵逼钨丝的套路题了。。。
题目要求:$$Ans=\sum_{i=1}^n\sum_{j=1}^mf(gcd(i,j)),f(x)=\max_{i=1}^ka_k,x=\prod_{i=1}^kp_i^{a_i}$$
很显然嘛,反演一波。
不会?先看这题:BZOJ3529: [Sdoi2014]数表
于是:$$Ans=\sum_{D=1}^n\lfloor\frac{n}{D}\rfloor\lfloor\frac{m}{D}\rfloor\sum_{d|D}\mu(\frac{D}{d})f(d)$$
前面的直接数论分块,后面的,额,这次不能暴力$O(n\log_2n)$了。。。
怎么办?
设$F(D)=\sum_{d|D}\mu(\frac{D}{d})f(d)$,然后分类讨论一波:

$$Ans=\sum_{D=1}^n\lfloor\frac{n}{D}\rfloor\lfloor\frac{m}{D}\rfloor\sum_{d|D}\mu(\frac{D}{d})f(d)$$

首先设$D=\prod_{i=1}^kp_i^{x_i},d=\prod_{i=1}^kp_i^{y_i}$。

要使$\mu(\frac{D}{d})!=0$,必须满足$y_i=x_i$或者$y_i=x_{i−1}$。

令$a=\max_{i=1}^kx_i$,则$f(d)=a\text{或}a-1$。

假设$D$中一共有$q$个质因子的指数为$a$。

  1. $q==k$:

  • $f(d)=a$:

$$\sum_{f(d)=a}\mu(\frac{D}{d})f(d)=a\times\sum_{f(d)=a}\mu(\frac{D}{d})=a\times\sum_{i=1}^k(-1)^{k-i}C_k^i=a\times (-1)^{k+1}$$

  • $f(d)=a−1$:

$$\sum_{f(d)=a-1}f(d)\mu(\frac{D}{d})=(a-1)\times\sum_{f(d)=a-1}\mu(\frac{D}{d})=(a-1)\times(-1)^k$$

所以当$q==k$时,$$F(D)=a\times(-1)^k+1+(a-1)\times(-1)^k=(-1)^k+1$$

  2. $q<k$:

  • $f(d)=a$:

$$\sum_{f(d)=a}f(d)\mu(\frac{D}{d})=a\times\sum_{f(d)=a}\mu(\frac{D}{d})=a\times\sum_{i=1}^q(-1)^{q-i}C_q^i\times\sum_{j=0}^{k-q}(-1)^jC_{k-q}^j=0$$

  • $f(d)=a−1$:

$$\sum_{f(d)=a-1}f(d)\mu(\frac{D}{d})=(a-1)\times\sum_{f(d)=a-1}\mu(\frac{D}{d})=(a-1)\times(-1)^q\times\sum_{j=0}^{k-q}(-1)^jC_{k-q}^j=0$$

所以当$q<k$时,$F(D)=0$。

知道这些,我们可以线筛的时候记录一下最小质因子出现的次数和除去最小质因子$p_i^{x_i}$后的数,然后判断幂指数是否相等。

所以把线性筛魔改下就好辣!

复杂度是$O(N+T\sqrt n)$。

附代码:

#include<iostream>
#include<algorithm>
#include<cstdio>
#define MAXN 10000010
using namespace std;
int k=0,prime[MAXN],t[MAXN],last[MAXN];
long long sum[MAXN];
bool np[MAXN];
inline int read(){
	int date=0,w=1;char c=0;
	while(c<'0'||c>'9'){if(c=='-')w=-1;c=getchar();}
	while(c>='0'&&c<='9'){date=date*10+c-'0';c=getchar();}
	return date*w;
}
void make(){
	int m=MAXN-10;
	for(int i=2;i<=m;i++){
		if(!np[i]){
			prime[++k]=i;
			last[i]=t[i]=1;
			sum[i]=1;
		}
		for(int j=1;j<=k&&prime[j]*i<=m;j++){
			int x=prime[j]*i;
			np[x]=true;
			if(i%prime[j]==0){
				last[x]=last[i];
				t[x]=t[i]+1;
				if(last[x]==1)sum[x]=1;
				else sum[x]=(t[last[x]]==t[x]?-sum[last[x]]:0);
				break;
			}
			last[x]=i;
			t[x]=1;
			sum[x]=(t[i]==1?-sum[i]:0);
		}
	}
	for(int i=1;i<=m;i++)sum[i]+=sum[i-1];
}
long long solve(int n,int m){
	long long ans=0;
	if(n>m)swap(n,m);
	for(int i=1,last=1;i<=n;i=last+1){
		last=min(n/(n/i),m/(m/i));
		ans+=1LL*(sum[last]-sum[i-1])*(n/i)*(m/i);
	}
	return ans;
}
int main(){
	make();
	int t=read();
	while(t--){
		int n=read(),m=read();
		printf("%lld\n",solve(n,m));
	}
    return 0;
}

 

posted @ 2018-08-20 09:44  符拉迪沃斯托克  阅读(278)  评论(0编辑  收藏  举报
Live2D