【BZOJ2693】jzptab

Time Limit: 5000 ms Memory Limit: 512 MB

description

给你\(n, m\),求\(\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{m} lcm(i,j)\)

答案对100000009取模。

多组数据。

input

第一行有一个正整数tt表示数据组数

接下来tt行每行有两个正整数n,mn,m

output

tt行,第ii行为第ii组询问的答案。

sample input

1
4 5

sample output

122

HINT

对于100%的数据:\(t≤10000,n,m≤10^7\)

\(100000009\)不是一个质数。


solution

做了几题之后感觉。。推起来稍微顺手一点不对顺脑一点了qwq?

(结果这题还是做了很久嗯qwq)

首先还是先写式子咯

\[\begin{aligned} ans&=\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{m} lcm(i,j)\\ &=\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{m}\frac{ij}{gcd(i,j)}&(抱歉lcm你长得太丑了)\\ &=\sum\limits_{k=1}^{min(n,m)}k\sum\limits_{i=1}^{\lfloor\frac{n}{k}\rfloor}\sum\limits_{j=1}^{\lfloor\frac{m}{k}\rfloor}ij[gcd(i,j)=1]\\ \\ &这里的话稍微说明一下,我们枚举i和j的gcd(记为k)\\&然后原来的i可以表示为i_0*k,原来的j表示为j_0*k,\\&\frac{ij}{gcd(i,j)}就变成了i_0*j_0*k,所以就变成了上面那样\\ \\ &=\sum\limits_{k=1}^{min(n,m)}k\sum\limits_{i=1}^{\lfloor\frac{n}{k}\rfloor}\sum\limits_{j=1}^{\lfloor\frac{m}{k}\rfloor}ij\sum\limits_{d|i,d|j}\mu(d)&(\sum\limits_{d|gcd(i,j)}\mu(d)=[gcd(i,j)=1])\\ &=\sum\limits_{k=1}^{min(n,m)}k\sum\limits_{d=1}^{min(\lfloor \frac{n}{k}\rfloor,\lfloor \frac{m}{k}\rfloor)}\mu(d)\sum\limits_{i=1}^{\lfloor \frac{n}{k}\rfloor}i[d\mid i]\sum\limits_{j=1}^{\lfloor \frac{m}{k}\rfloor}j[d\mid j]\\ \\ &观察一下\sum\limits_{i=1}^{\lfloor \frac{n}{k}\rfloor}i[d\mid i],会发现其实这个式子求的就是1到\lfloor \frac{n}{k}\rfloor范围内d的倍数的和\\ \\ &=\sum\limits_{k=1}^{min(n,m)}k\sum\limits_{d=1}^{min(\lfloor \frac{n}{k}\rfloor,\lfloor \frac{m}{k}\rfloor)}\mu(d) (sum(\lfloor \frac{n}{kd}\rfloor)d)(sum(\lfloor \frac{m}{kd}\rfloor)d)&(sum(n)=\sum\limits_{i=1}{n}=\frac{n(n+1)}{2})\\ &=\sum\limits_{T=1}^{min(n,m)}sum(\lfloor \frac{n}{T}\rfloor)sum(\lfloor \frac{m}{T}\rfloor)\sum\limits_{d\mid T}\mu(d)d^2 \frac{T}{d}&(T = kd) \end{aligned} \]

化到这一步,我们发现前面的\(sum\)的部分可以直接分块根号搞定(bzoj2820)

后面的东西看起来十分眼熟啊,我们令\(g(x)=\sum\limits_{d\mid x}\mu(d)d^2 \frac{x}{d}\),令\(f(x)=\sum\limits_{d|x}d^2\mu(d)\),令\(h(x)=x\)

那么\(g(x) = \sum\limits_{d\mid x}f(d)h(\frac{x}{d})\),然后由于\(f(d)\)\(h(\frac{x}{d})\)都是积性函数,所以\(g(x)\)也是积性函数

考虑怎么求\(g(x)\)

我们考虑把这个东西筛出来,按着线性筛的思路来分析一下,求解\(g(x)\)的值

如果说\(x\)为质数,那么显然\(g(x) = x - x^2\)

如果\(x\)不为质数,我们设\(x = i * p\),其中\(p\)为质数,那么有两种情况

  1. \(p \nmid i\) ,由于\(i\)\(p\)互质而\(g(x)\)为积性函数,\(g(x) = g(i*p) = g(i) * g(p)\)

  2. \(p\mid i\),这个时候就有点。。不是很好搞了。。

    我们可以把\(i\)表示为\(t * p^k\)\(t\)\(p\)互质)

    那么我们就尝试一下从乘了一个\(p\)会有什么影响这个方面来考虑一下

    考虑\(g(p^k)\)的值,显然根据\(\mu\)的定义,只有\(\mu(1)\)\(\mu(p)\)能够提供贡献(其他的\(p\)的指数都>1,所以都是0)

    那么我们就可以得到\(g(p^k) = f(1)p^{k} + f(p)p^{k-1}\)

    然后写出\(g(p^{k+1})\)的表达式,会发现是\(f(1)p^{k+1} + f(p)p^{k}\)

    也就是说\(g(p^{k+1}) = g(p^k) p\)

    那么就可以得到\(g(x) = g(i * p) = g(t * p^k *p) = g(t) * g(p^{k}) * p = g(x) * p\)

然后就可以顺利筛出来啦

那这题好像就十分愉快地做完了ovo


#include<iostream>
#include<cstdio>
#include<cstring>
#define MOD 100000009
#define ll long long
using namespace std;
const int MAXN=1e7+10;
ll p[MAXN],g[MAXN],s[MAXN];
bool vis[MAXN];
int ans;
int n,m,T,pos,tmp;
int prework(int n);

int main(){
#ifndef ONLINE_JUDGE
	freopen("a.in","r",stdin);
	freopen("a.out","w",stdout);
#endif
	scanf("%d",&T);
	prework(10000000);
	for (int o=1;o<=T;++o){
		scanf("%d%d",&n,&m);
		if (n>m) swap(n,m);
		pos=ans=0;
		for (int i=1;i<=n;i=pos+1){
			pos=min(n/(n/i),m/(m/i));
			ll tmp=(s[n/i]*s[m/i]%MOD*(g[pos]-g[i-1])%MOD)%MOD;
			ans=((ll)ans+tmp+MOD)%MOD;
		}
		printf("%d\n",ans);
	}
}

int prework(int n){
	g[1]=1; s[1]=1;
	int cnt=0;
	memset(vis,false,sizeof(vis));
	for (int i=2;i<=n;++i){
		s[i]=(ll)i*(i+1)/2%MOD;
		if (!vis[i]){
			g[i]=(i-(ll)i*i%MOD+MOD)%MOD;
			p[++cnt]=i;
		}
		for (int j=1;j<=cnt&&i*p[j]<=n;++j){
			vis[i*p[j]]=true;
			if (i%p[j])
				g[i*p[j]]=g[i]*g[p[j]]%MOD;
			else{
				g[i*p[j]]=g[i]*p[j]%MOD;
				break;
			}
		}
	}
	for (int i=1;i<=n;++i)
		g[i]=(g[i]+g[i-1])%MOD;
}

posted @ 2018-01-07 20:18  yoyoball  阅读(200)  评论(0编辑  收藏  举报