简单的数学题

题意:

(sum_{i=1}^{n}sum_{j=1}^{n}{ijgcd(i,j)},n<=1e10)


题解

先把式子化简一下
(sum_{i=1}^{n}sum_{j=1}^{n}{ijgcd(i,j)}\sum_{d=1}^{n}sum_{i=1}^{n}sum_{j=1}^{n}{ijgcd(i,j)}\sum_{d=1}^{n}{d^3}sum_{i=1}^{n/d}sum_{j=1}^{n/d}{ij[gcd(i,j)=1]})
然后还是设(F(t)=sum_{i=1}^{n/d}sum_{j=1}^{n/d}{ij[t|gcd(i,j)]})
(F(t)=t^2sum_{i=1}^{n/dt}sum_{j=1}^{n/dt}{ij})
(B(n)=sum_{i=1}^{n}i)
所以原式就是(sum_{d=1}^{n}{d^3}{f(1)})
(sum_{d=1}^{n}{d^3}sum_{i=1}^{n/d}{mu(i)i^2B(frac{n}{id})^2})
还是老套路设(T=id)
(sum_{T=1}^{n}{B(frac{n}{T})^2}sum_{d|T}{mu(frac{T}{d})(frac{T}{d})^2d^3})
(sum_{T=1}^{n}{B(frac{n}{T})^2}T^2sum_{d|T}{mu(frac{T}{d})d})
然后如果(n<=1e7)直接线筛就可以做了
但是杜教筛似乎不好筛以狄利克雷卷积的形式定义的函数
但是看后面的东西我们想到了什么?
(mu*id=phi)
所以后面那个东西就是(phi(T))
所以我们就只需要去筛(f(T)=T^2phi(T)了)
那么我们考虑用什么作为(g)函数
(sum_{d|T}{phi(d)d^2g(frac{T}{d})})
似乎(g=id^2)就很好
这样就成了(sum_{d|T}{phi(d)id(T)^2})
然后把(id(T)^2)提前
就成了(id(T)^2sum_{d|T}{phi(d)}\=id(T)^2id(T)\=id(T)^3)
这样就可以筛了

代码

#include<map>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
# define LL long long
const int M = 4000005 ;
using namespace std ;

bool notp[M] ;
int pnum , p[M] , upp = 4000000 ;
LL mod , n , sum[M] , ans , inv2 , inv6 ;
map < LL , LL > psum ;

inline LL dc(LL n) { 
	n %= mod ;
	return n % mod * (n + 1) % mod * inv2 % mod; 
}
inline LL dc2(LL n) { 
	n %= mod ;
	return n % mod * (n + 1) % mod * (n * 2 + 1) % mod * inv6 % mod ; 
}
inline LL Fpw(LL Base , LL k) {
	LL temp = 1 ; Base %= mod ; k %= (mod - 1) ;
	while(k) {
		if(k & 1) temp = temp * Base % mod ;
		Base = Base * Base % mod ; k >>= 1 ;
	}
	return temp ;
}
inline void Presolve(int n) {
	sum[1] = 1 ; 
	for(int i = 2 ; i <= n ; i ++) {
		if(!notp[i]) {
			p[++pnum] = i ;
			sum[i] = (i - 1 + mod) % mod ;
		}
		for(int j = 1 ; j <= pnum && 1LL * i * p[j] <= n ; j ++) {
			notp[i * p[j]] = true ;
			if(i % p[j] == 0) sum[i * p[j]] = sum[i] * p[j] % mod ;
			else sum[i * p[j]] = sum[i] * sum[p[j]] % mod ;
		}
	}
	for(int i = 1 ; i <= n ; i ++)
		sum[i] = (sum[i - 1] + sum[i] * i % mod * i % mod) % mod ;
}

inline LL Sum(LL n) {
	if(n <= upp) return sum[n] ;
	if(psum[n]) return psum[n] ;
	LL ret = dc(n) * dc(n) % mod ;
	for(LL l = 2 , r ; l <= n ; l = r + 1) {
		r = n / (n / l) ;
		LL tp = ((dc2(r) - dc2(l - 1)) % mod + mod) % mod ;
		ret = ((ret - tp * Sum(n / l) % mod) % mod + mod) % mod ;
	}
	ret %= mod ;
	psum[n] = ret ; return ret ;
}
int main() {
	scanf("%lld%lld",&mod,&n) ;
	inv2 = Fpw(2 , mod - 2) ;
	inv6 = Fpw(6 , mod - 2) ;
	Presolve(min(n , 4000000LL)) ;
	for(LL l = 1 , r ; l <= n ; l = r + 1) {
		r = n / (n / l) ;
		LL tp = ((Sum(r) - Sum(l - 1)) % mod + mod) % mod ;
		ans = (ans + (tp * dc(n / l) % mod * dc(n / l) % mod + mod) % mod + mod) % mod ;
	}
	printf("%lld
",(ans % mod + mod) % mod) ;
	return 0 ;
}
原文地址:https://www.cnblogs.com/beretty/p/10434984.html