简单的数学题

题意:

\(\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^2\sum_{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^2\sum_{d|T}{\mu(\frac{T}{d})d}\)
然后如果\(n<=1e7\)直接线筛就可以做了
但是杜教筛似乎不好筛以狄利克雷卷积的形式定义的函数
但是看后面的东西我们想到了什么?
\(\mu*id=\phi\)
所以后面那个东西就是\(\phi(T)\)
所以我们就只需要去筛\(f(T)=T^2\phi(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)^2\sum_{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\n",(ans % mod + mod) % mod) ;
	return 0 ;
}
posted @ 2019-02-26 07:00  beretty  阅读(189)  评论(0编辑  收藏  举报