洛谷3768:简单的数学题

洛谷3768:简单的数学题

题意描述:

  • \([\sum_{i=1}^n\sum_{j=1}^nijgcd(i,j)]\ mod\ p\)
  • 数据范围\(n\leq10^{10},p\)为质数(long long)。

思路:

首先这个\(n\)的数据范围大概率是要杜教筛的节奏啊。

先化式子。

枚举\(gcd(i,j)=d\)

  • \(\sum_{d=1}^nd\sum_{i=1}^n\sum_{j=1}^nij[gcd(i,j)=d]\).

提取\(d\)

  • \(\sum_{d=1}^nd^3\sum_{i=1}^\frac{n}{d}\sum_{j=1}^\frac{n}{d}ij[gcd(i,j)=1]\).

我们知道,从\(1\)\(n\)中与\(n\)互质的数的和为:

  • \(\sum_{i=1}^ni[gcd(i,n)=1]=\frac{n*\varphi(n)}{2}\).

提一下:

  • \(\sum_{d=1}^nd^3\sum_{i=1}^\frac{n}{d}i\sum_{j=1}^\frac{n}{d}j[gcd(i,j)=1]\).

原式就等于:

  • \(\sum_{d=1}^nd^3\sum_{i=1}^\frac{n}{d}i*i*\varphi(i)\).

前面\(\frac{n}{d}\)\(\sqrt{n}\)种选择,所以可以数论分块一下,后面的算是很明显的杜教筛了。

\(f=\varphi idid,S(n)=\sum_{i=1}^nf(i)\)。设\(g(i)=idid\)

那么有:

  • \((f*g)(n)=\sum_{d|n}(\varphi(d)d^2)\frac{n^2}{d^2}=n^3\)

这玩意前缀和是\(\frac{n^2(n+1)^2}{4}\)

根据杜教筛有:

  • \(g(1)S(n)=\sum_{i=1}^n(f*g)(i)-\sum_{i=2}^ng(i)S(\frac{n}{i})\).

也就是\(S(n)=\frac{n^2(n+1)^2}{4}-\sum_{i=2}^ni^2S(\frac{n}{i})\)

原式就是:

  • \(\sum_{d=1}^nd^3S(\frac{n}{d})\).
#include
using namespace std;
typedef long long ll;
int inv[15];
const int maxn = 5e6;
ll n, mod;

void get_inv(int n){
    inv[1] = 1;
    for(int i = 2; i <= n; i++)
    inv[i] = ((ll)(mod-mod/i)*inv[mod%i])%mod;
}

int primes[maxn+10], cnt;
bool vis[maxn+10];
ll phi[maxn+10];
void init(int n)
{
    phi[1] = 1;
    for(int i = 2; i <= n; i++)
    {
        if(!vis[i])
        {
            primes[++cnt] = i;
            phi[i] = i-1;
        }
        for(int j = 1; primes[j] <= n/i; j++)
        {
            vis[primes[j]*i] = 1;
            if(i % primes[j] == 0)
            {
                phi[primes[j]*i] = phi[i]*primes[j];
                break;
            }
            else phi[i*primes[j]] = phi[i]*(primes[j]-1);
        }
    }
    for(ll i = 1; i <= n; i++)
    phi[i] = (phi[i-1]%mod+i%mod*i%mod*phi[i]%mod)%mod;
}

inline ll get_cube(ll n){
    n %= mod;
    return n%mod*(n+1)%mod*(2*n+1)%mod*inv[6]%mod;
}

unordered_map Sphi;

ll getSphi(ll n)
{
    if(n <= maxn) return phi[n];
    if(Sphi[n]) return Sphi[n];
    ll res = n%mod*n%mod*(n+1)%mod*(n+1)%mod*inv[4]%mod;
    for(ll l = 2, r; l <= n; l = r+1)
    {
        r = n/(n/l);
        res -= getSphi(n/l)%mod*(((get_cube(r)-get_cube(l-1))%mod)+mod)%mod;
        res = (res%mod+mod)%mod;
    } return Sphi[n] = res;
}

inline ll get_n3(ll n){
    n %= mod;
    return n%mod*n%mod*(n+1)%mod*(n+1)%mod*inv[4]%mod;
}

int main()
{
    cin >> mod >> n; get_inv(10);
    init(maxn);
    ll ans = 0;
    for(ll l = 1, r; l <= n; l = r+1)
    {
        r = n/(n/l);
        ans = (ans+(((get_n3(r)-get_n3(l-1))%mod)+mod)%mod*getSphi(n/l)%mod) % mod;
    }
    cout << ans << endl;
    return 0;
}

你可能感兴趣的:(洛谷3768:简单的数学题)