• LG P3768 简单的数学题


    ( ext{Problem})

    [left(sum_{i=1}^n sum_{j=1}^n i j gcd(i,j) ight) mod p ]

    (n le 10^{10},5 imes 10^8 le p le 1.1 imes 10^9)(p in mathbb{P})

    ( ext{Solution})

    显然走欧拉反演

    [egin{aligned} sum_{i=1}^n sum_{j=1}^n i j gcd(i,j) &= sum_{i=1}^n sum_{j=1}^n i j sum_{d|gcd(i,j)} varphi(d) \ &= sum_{d=1}^n varphi(d) sum_{d|i} i sum_{d|j} j \ &= sum_{d=1}^n varphi(d) sum_{i=1}^{lfloor frac n d floor} i sum_{j=1}^{lfloor frac n d floor} j \ &= sum_{d=1}^n d^2 varphi(d) S^3 (lfloor frac n d floor) end{aligned} ]

    (varphi) 后面的部分可以用等差数列求和公式的平方得到(它恰恰连续自然数三次方和的求和公式)
    这个式子显然可以数论分块(非常显然)
    那么重点就是求 (S(n)=sum_{d=1}^n d^2 varphi(d))
    杜教筛即可

    即考虑卷积 (f * g),记 (f(n)=n^2 varphi(n)),令 (g = ID^2)

    [(f * g)(n) = sum_{d|n} f(d) g(frac{n}{d}) = sum_{d|n} d^2 varphi(d) left(frac{n}{d} ight)^2 = n^2 sum_{d|n} varphi(d) = n^3 ]

    那么

    [egin{aligned} g(1)S(n)=sum_{i=1}^n (f*g)(n) - sum_{i=2}^n g(i)S(lfloor frac n i floor) \ S(n) = sum_{i=1}^n i^3 - sum_{i=2}^n i^2 S(lfloor frac n i floor) end{aligned} ]

    仍然可以数论分块,利用平方和与立方和公式快速计算

    ( ext{Code})

    #include<cstdio>
    #include<tr1/unordered_map>
    #define LL long long
    #define maxn 5000000
    #define N 5000005
    using namespace std;
    
    int vis[N], phi[N], prime[N], totp;
    LL P, n, inv6, sf[N];
    tr1::unordered_map<LL, LL> SF;
    
    inline LL fpow(LL x, LL y)
    {
    	LL res = 1;
    	for(; y; y >>= 1)
    	{
    		if (y & 1) res = res * x % P;
    		x = x * x % P;
    	}
    	return res;
    }
    inline LL S2(LL n)
    {
    	n %= P;
    	return n * (n + 1) % P * (n * 2 + 1) % P * inv6 % P;
    }
    inline LL S3(LL n)
    {
    	n %= P;
    	return n * (n + 1) / 2 % P * (n * (n + 1) / 2 % P) % P;
    }
    
    inline void sieve()
    {
    	vis[1] = phi[1] = 1;
    	for(register int i = 2; i <= maxn; i++)
    	{
    		if (!vis[i]) prime[++totp] = i, phi[i] = i - 1;
    		for(register int j = 1; j <= totp && prime[j] * i <= maxn; j++)
    		{
    			vis[i * prime[j]] = 1;
    			if (i % prime[j]) phi[i * prime[j]] = phi[i] * phi[prime[j]];
    			else{phi[i * prime[j]] = phi[i] * prime[j]; break;}
    		}
    	}
    	for(register int i = 1; i <= maxn; i++) sf[i] = (sf[i - 1] + (LL)i * i % P * phi[i] % P) % P;
    }
    
    LL SumF(LL n)
    {
    	if (n <= maxn) return sf[n];
    	if (SF[n]) return SF[n];
    	LL res = S3(n), r;
    	for(register LL l = 2; l <= n; l = r + 1)
    	{
    		r = n / (n / l);
    		res = (res - (S2(r) - S2(l - 1) + P) % P * SumF(n / l) % P + P) % P;
    	}
    	return SF[n] = res;
    }
    
    int main()
    {
    	scanf("%lld%lld", &P, &n);
    	sieve();
    	LL ans = 0, r; inv6 = fpow(6, P - 2);
    	for(register LL l = 1; l <= n; l = r + 1)
    	{
    		r = n / (n / l);
    		ans = (ans + S3(n / l) * (SumF(r) - SumF(l - 1) + P) % P) % P;
    	}
    	printf("%lld
    ", ans);
    }
    
  • 相关阅读:
    Physics Experiment POJ3684
    FLIPTILE POJ NO.3279
    [蓝桥杯][算法提高VIP]盾神与积木游戏
    棋盘问题
    出栈次数的DFS计算
    Bribe the Prisoners
    Crazy Rows
    关于部分“记录”密码获取^o^/
    NOIP2017爆炸记
    【luogu 1024 一元三次方程求解】二分思想
  • 原文地址:https://www.cnblogs.com/leiyuanze/p/15027441.html
Copyright © 2020-2023  润新知