洛谷3768 简单的数学题

版权声明:写得不好,转载请通知一声,还请注明出处,感激不尽 https://blog.csdn.net/As_A_Kid/article/details/86655058

Problem

洛谷
i = 1 n j = 1 n i j gcd ( i , j ) \sum_{i=1}^n\sum_{j=1}^n ij\gcd(i,j)

Solution

为了方便表达,下文中约定 S 1 ( n ) = 1 + 2 + + n S_1(n)=1+2+\cdots+n


(1) d = 1 n d i = 1 n j = 1 n i j [ gcd ( i , j ) = d ] \sum_{d=1}^nd\sum_{i=1}^{n}\sum_{j=1}^{n}ij[\gcd(i,j)=d] \tag{1}

(2) d = 1 n d 3 i = 1 n / d j = 1 n / d i j [ gcd ( i , j ) = 1 ] \sum_{d=1}^nd^3\sum_{i=1}^{n/d}\sum_{j=1}^{n/d}ij[\gcd(i,j)=1] \tag{2}

考虑把后面的式子莫反。设 F ( n ) = i = 1 x j = 1 x i j [ gcd ( i , j ) = n ] F(n)=\sum_{i=1}^x\sum_{j=1}^xij[\gcd(i,j)=n] ,构造
(3) G ( n ) = n d F ( d ) = ( n d d ) 2 = n 2 S 1 ( x d ) 2 G(n)=\sum_{n|d}F(d)=(\sum_{n|d} d)^2=n^2S_1(\frac x d)^2\tag{3}

反演得
(4) F ( 1 ) = i = 1 x μ ( i ) G ( i ) F(1)=\sum_{i=1}^x \mu(i)G(i)\tag{4}
( 4 ) (4) 代入 ( 2 ) (2) 中,式子变为
(5) d = 1 n d 3 i = 1 n / d μ ( i ) i 2 S 1 ( n i d ) 2 \sum_{d=1}^n d^3\sum_{i=1}^{n/d}\mu(i)i^2S_1(\frac n {id})^2\tag{5}

(6) i d = 1 n S 1 ( n i d ) 2 i d 2 φ ( i d ) \sum_{id=1}^n S_1(\frac n {id})^2id^2\varphi(id)\tag{6}

前面数论分块,后面是一个积性函数,注意到 n 1 0 10 n\leq 10^{10} ,考虑杜教筛

不妨令后面的函数为 f ( n ) = n 2 φ ( n ) f(n)=n^2\varphi(n) ,那么我们构造一个 g g 。考虑它们的狄利克雷卷积 ( f g ) ( n ) = d n d 2 φ ( d ) g ( n d ) (f*g)(n)=\sum_{d|n}d^2\varphi(d)g(\frac n d)

不妨令 g ( n ) = n 2 g(n)=n^2 ,就可以消掉 d d 了,即 ( f g ) ( n ) = n 3 (f*g)(n)=n^3

套用式子即可。 S ( n ) = ( n ( n + 1 ) ) 2 4 i = 2 n g ( i ) S ( n / i ) S(n)=\frac {(n(n+1))^2} {4}-\sum_{i=2}^n g(i)S(n/i)

Code

#include <cstdio>
#include <map>
using namespace std;
typedef long long ll;
const int maxn=10000010,N=10000000;
template <typename Tp> inline int getmin(Tp &x,Tp y){return y<x?x=y,1:0;}
template <typename Tp> inline int getmax(Tp &x,Tp y){return y>x?x=y,1:0;}
template <typename Tp> inline void read(Tp &x)
{
    x=0;int f=0;char ch=getchar();
    while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
    if(ch=='-') f=1,ch=getchar();
    while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    if(f) x=-x;
}
int mod,inv6,ans,tot,pri[1000010],phi[maxn];
ll n;
map<ll,int> ma;
map<ll,int>::iterator itr;
int pls(int x,int y){return x+y>=mod?x+y-mod:x+y;}
int dec(int x,int y){return x-y<0?x-y+mod:x-y;}
int sum(ll x){if(x>=mod) x%=mod;return (ll)x*(x+1)/2%mod;}
int sum2(ll x){if(x>=mod) x%=mod;return (ll)x*(x+1)%mod*(x+x+1)%mod*inv6%mod;}
int power(int x,int y)
{
	int res=1;
	for(;y;y>>=1,x=(ll)x*x%mod)
	  if(y&1)
	    res=(ll)res*x%mod;
	return res;
}
void init()
{
	phi[1]=1;inv6=power(6,mod-2);
	for(int i=2;i<=N;i++)
	{
		if(!phi[i]) phi[i]=i-1,pri[++tot]=i;
		for(int j=1;j<=tot&&i*pri[j]<=N;j++)
		{
			if(i%pri[j]==0)
			{
				phi[i*pri[j]]=phi[i]*pri[j];
				break;
			}
			phi[i*pri[j]]=phi[i]*(pri[j]-1);
		}
	}
	for(int i=2;i<=N;i++) phi[i]=pls((ll)phi[i]*i%mod*i%mod,phi[i-1]);
}
int work(ll x)
{
	if(x<=N) return phi[(int)x];
	if((itr=ma.find(x))!=ma.end()) return itr->second;
	int res=sum(x);res=(ll)res*res%mod;
	for(ll i=2,j;i<=x;i=j+1)
	{
		j=x/(x/i);
		res=dec(res,(ll)dec(sum2(j),sum2(i-1))*work(x/i)%mod);
	}
	return ma[x]=res;
}
int main()
{
	#ifndef ONLINE_JUDGE
	freopen("in.txt","r",stdin);
	#endif
	read(mod);read(n);
	init();
	for(ll i=1,j,tmp;i<=n;i=j+1)
	{
		j=n/(n/i);tmp=sum(n/i);tmp=(ll)tmp*tmp%mod;
		ans=pls(ans,tmp*dec(work(j),work(i-1))%mod);
	}
	printf("%d\n",ans);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/As_A_Kid/article/details/86655058