[51Nod 1220]

题面

d(n)d(n)表示nn的约数之和求
i=1nj=1nd(ij)largesum_{i=1}^nsum_{j=1}^nd(ij)

题目分析

先给结论
d(ij)=xiyjxj/y[(x,y)==1]large d(ij)=sum_{x|i}sum_{y|j}xj/y[(x,y)==1]
可以通过 传送门 类似的证明方法证明
拖更…

AC code
#include <cstdio>
#include <map>
#include <algorithm>
using namespace std;
typedef long long LL;
const int MAXN = 1e6 + 1, mod = 1e9 + 7;
int Prime[MAXN/10], Cnt, mu[MAXN];
bool IsnotPrime[MAXN];
inline void init(int n)
{
	mu[1] = 1;
	for(int i = 2; i <= n; ++i)
	{
		if(!IsnotPrime[i])
			Prime[++Cnt] = i, mu[i] = -1;
		for(int j = 1, v; j <= Cnt && i * Prime[j] <= n; ++j)
		{
			v = i * Prime[j];
			IsnotPrime[v] = 1;
			if(i % Prime[j] == 0) { mu[v] = 0; break; }
			mu[v] = -mu[i];
		}
	}
	for(int i = 1; i <= n; ++i)
		mu[i] = (mu[i-1] + i*mu[i]%mod) % mod;
}
map<int, int>s;

inline int f(int i, int j) //i+(i+1)+...+j
{
	return ((LL)(i+j) * (j-i+1)/2) % mod;
}

inline int sum(int n) //mu(1)1+mu(2)2+...+mu(n)n
{
	if(n < MAXN) return mu[n];
	if(s.count(n)) return s[n];
	int ret = 1;
	for(int i = 2, j; i <= n; i=j+1)
	{
		j = n/(n/i);
		ret = (ret - (LL)f(i,j) * sum(n/i) % mod) % mod;
	}
	return s[n]=ret;
}

inline int calc(int n)
{
	int ret = 0, k;
	for(int i = 1, j; i <= n; i=j+1)
	{
		j = n/(n/i); k = n/i;
		ret = (ret + (LL)(j-i+1) * (((LL)k*(k+1)/2)%mod) % mod) % mod;
	}
	return ret;
}

inline int solve(int n)
{
	int ret = 0, last = 0, tmp, tmp2;
	for(int i = 1, j; i <= n; i=j+1)
	{
		tmp = sum(j = n/(n/i)), tmp2 = calc(n/i), tmp2 = (LL)tmp2 * tmp2 % mod;
		ret = (ret + (LL)(tmp - last) * tmp2 % mod) % mod;
		last = tmp;
	}
	return ret;
}

int main ()
{
	int n; init(MAXN-1);
	scanf("%d", &n);
	printf("%d
", (solve(n)+mod)%mod);
}
原文地址:https://www.cnblogs.com/Orz-IE/p/12039454.html