[51 Nod 1584] 加权约数和

题意


求$$\large \sum_{i=1}^N\sum_{j=1}^Nmax(i,j)\cdot\sigma_1(ij)$$
其中
$1\le N\le10^6$
$1\le T\le5\cdot10^4$
$\sigma_1(n)$表示$n$的约数和
### 题目分析
令$A=\sum_{i=1}^n\sum_{j=1}^ii\cdot\sigma_1(ij),B=\sum_{i=1}^ni\cdot\sigma_1(i^2)$,则$Ans=2A-B$

且有
$$\large
\begin{aligned}
A&=\sum_{i=1}^ni\cdot\sum_{j=1}^i\sum_{x|i}\sum_{y|j}x\cdot j/y[(x,y)=1]\\
&=\sum_{i=1}^ni\cdot\sum_{j=1}^i\sum_{x|i}\sum_{y|j}x\cdot j/y\sum_{d|(x,y)}\mu(d)\\
&=\sum_{d=1}^n\mu(d)\sum_{d|x}x\sum_{x|i}i\sum_{d|y}\sum_{y|j}^i\frac jy\\
&=\sum_{d=1}^n\mu(d)\sum_{x=1}^{\lfloor\frac nd\rfloor}dx\sum_{x|i}^{\lfloor\frac nd\rfloor}di\sum_{y=1}^{\lfloor\frac nd\rfloor}\sum_{y|j}^i\frac{dj}{dy}\\
&=\sum_{d=1}^n\mu(d)d^2\sum_{i=1}^{\lfloor\frac nd\rfloor}i\sum_{x|i}x\sum_{y=1}^{\lfloor\frac nd\rfloor}\sum_{y|j}^iy\\
&=\sum_{d=1}^n\mu(d)d^2\sum_{i=1}^{\lfloor\frac nd\rfloor}i\cdot\sigma_1(i)\sum_{j=1}^{i}\sigma_1(j)\\
&=\sum_{d=1}^n\mu(d)d^2\sum_{i=1}^{\lfloor\frac nd\rfloor}i\cdot\sigma_1(i)\cdot S_{\sigma_1}(i)\\\end{aligned}$$
$$\large
\begin{aligned}
B&=\sum_{i=1}^ni\sum_{x|i}\sum_{y|i}x\cdot i/y[(x,y)=1]\\
&=\sum_{i=1}^ni\cdot\sum_{x|i}\sum_{y|i}x\cdot i/y\sum_{d|(x,y)}\mu(d)\\
&=\sum_{d=1}^n\mu(d)\sum_{d|i}i\sum_{d|x|i}\sum_{d|y|i}x\cdot \frac iy\\
&=\sum_{d=1}^n\mu(d)\sum_{i=1}^{\lfloor\frac nd\rfloor}di\sum_{x|i}\sum_{y|i}dx\cdot \frac {di}{dy}\\
&=\sum_{d=1}^n\mu(d)d^2\sum_{i=1}^{\lfloor\frac nd\rfloor}i\sum_{x|i}x\sum_{y|i}\frac {i}{y}\\
&=\sum_{d=1}^n\mu(d)d^2\sum_{i=1}^{\lfloor\frac nd\rfloor}i\sum_{x|i}x\sum_{y|i}y\\
&=\sum_{d=1}^n\mu(d)d^2\sum_{i=1}^{\lfloor\frac nd\rfloor}i\cdot\sigma_1(i)^2\\
\end{aligned}$$
$$\large
\begin{aligned}
\therefore Ans(n)&=2A-B\\&=\sum_{d=1}^n\mu(d)d^2\sum_{i=1}^{\lfloor\frac nd\rfloor}i\cdot\sigma_1(i)(2\cdot S_{\sigma_1}(i)-\sigma_1(i))
\end{aligned}$$

发现$Ans(n)$可以递推:
$$Ans(n)=Ans(n-1)+\sum_{d|n}\mu(d)d^2{\lfloor\frac nd\rfloor}\cdot\sigma_1({\lfloor\frac nd\rfloor})(2\cdot S_{\sigma_1}({\lfloor\frac nd\rfloor})-\sigma_1({\lfloor\frac nd\rfloor}))$$
那么就可以$O(n\log n)$预处理了。

然后每次$O(1)$回答就完了。

 

 

代码

 

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 1000005;
const int mod = 1000000007;
int Cnt, Prime[N], mu[N];
LL ans[N], sd[N], a[N], d[N], f[N];
bool IsnotPrime[N];

void init() {
	d[1] = 1, a[1] = 1, mu[1] = 1;
	for(int i = 2; i < N; ++i) {
		if(!IsnotPrime[i])
			Prime[++Cnt] = i, d[i] = a[i] = 1+i, mu[i] = -1;
		for(int j = 1, k; j <= Cnt && i * Prime[j] < N; ++j) {
			IsnotPrime[k = i * Prime[j]] = 1;
			if(i % Prime[j] == 0) {
				mu[k] = 0;
				a[k] = a[i] * Prime[j] + 1;
				d[k] = d[i] / a[i] * a[k];
				break;
			}
			mu[k] = -mu[i];
			a[k] = 1 + Prime[j];
			d[k] = d[i] * a[k];
		}
	}
	for(int i = 1; i < N; ++i) {
		sd[i] = (sd[i-1] + (d[i]%=mod)) % mod;
		f[i] = i*d[i]%mod*(2*sd[i]-d[i]+mod)%mod;
	}
	for(int i = 1; i < N; ++i) if(mu[i])
		for(int j = i; j < N; j += i)
			ans[j] = (ans[j] + 1ll*mu[i]*i*i%mod*f[j/i]%mod + mod) % mod;
	for(int i = 1; i < N; ++i) ans[i] = (ans[i-1] + ans[i]) % mod;
}
int main () {
	init();
	int T, ks = 0, N; scanf("%d", &T);
	while(T--) scanf("%d", &N), printf("Case #%d: %lld\n", ++ks, ans[N]);
}

  

posted @ 2019-12-14 14:52  _Ark  阅读(91)  评论(0编辑  收藏  举报