P3768 简单的数学题 杜教筛*

P3768
杜教筛+狄利克雷卷积

题意

给出 n , p , ( n ≤ 1 0 10 ) n, p,(n\leq10^{10}) n,p,(n1010), 求 ( ∑ i = 1 n ∑ j = 1 n i j g c d ( i , j ) ) m o d    p (\sum_{i=1}^n\sum_{j=1}^nijgcd(i,j)) \mod p (i=1nj=1nijgcd(i,j))modp

思路

利用重要卷积 n = ϕ ∗ 1 n = \phi*1 n=ϕ1 替换 g c d ( i , j ) gcd(i,j ) gcd(i,j)
∑ i = 1 n ∑ j = 1 n i j g c d ( i , j ) = ∑ i = 1 n ∑ j = 1 n i j ∑ d ∣ i , d ∣ j ϕ ( d ) = ∑ d = 1 n ϕ ( d ) d 2 ∑ i = 1 n d i ∑ j = 1 n d j \sum_{i=1}^n\sum_{j=1}^nijgcd(i,j) = \sum_{i=1}^n\sum_{j=1}^nij\sum_{d|i,d|j}\phi(d)=\sum_{d=1}^n \phi(d)d^2\sum_{i=1}^\frac ndi\sum_{j=1}^{\frac nd}j i=1nj=1nijgcd(i,j)=i=1nj=1nijdi,djϕ(d)=d=1nϕ(d)d2i=1dnij=1dnj = ∑ d = 1 n ϕ ( d ) d 2 ( ∑ i = 1 n d i ) 2 =\sum_{d=1}^n\phi(d)d^2(\sum_{i=1}^{\frac nd}i)^2 =d=1nϕ(d)d2(i=1dni)2

上式后半部分可以 O ( 1 ) O(1) O(1) 求,考虑用杜教筛优化前半部分。
在这里插入图片描述
S ( n ) = ∑ d = 1 n ϕ ( d ) d 2 = ( n ( n + 1 ) 2 ) 2 − ∑ y = 2 n y 2 S ( n y ) S(n)=\sum_{d=1}^n\phi(d)d^2=(\frac {n(n+1)}2)^2-\sum_{y=2}^ny^2S(\frac ny) S(n)=d=1nϕ(d)d2=(2n(n+1))2y=2ny2S(yn)

附莫反做法
在这里插入图片描述

代码

int n, P;
ll power(ll a, ll b) {
    ll ans = 1;
    a = a % P;
    for(; b; b >>= 1) {
        if(b & 1) ans = ans * a % P;
        a = a * a % P;
    }
    return ans;
}
bool isnp[maxn];//maxn大小为n^(2/3)
vector<int> primes;
ll phi[maxn], sphi[maxn];//分别记录欧拉函数值及前缀和
map<ll, ll> umsphi;//存大于n^(2/3)的值
void init(int n) // 筛欧拉函数 n为n^(2/3)
{
    phi[1] = 1;
    for (int i = 2; i <= n; i++)
    {
        if (!isnp[i])
            primes.push_back(i), phi[i] = i - 1;
        for (int p : primes)
        {
            if (p * i > n)
                break;
            isnp[p * i] = 1;
            if (i % p == 0)
            {
                phi[p * i] = phi[i] * p;
                break;
            }
            else
                phi[p * i] = phi[p] * phi[i];
        }
    }
    for(int i = 1; i <= n; ++i)
        sphi[i] = (sphi[i - 1] + i * i % P * phi[i] % P) % P;
}
int inv2, inv6;
int s2(int x) {
    x %= P;
    return x * (x+1) % P * (2 * x + 1) % P * inv6 % P;
}
int s3(int x){
    x%=P;
    return (x*(x+1)/2)%P*((x*(x+1)/2)%P)%P;
}
int s4(int x){
    x%=P;
    return (x*(x+1)/2)%P;
}
ll sum_phi(ll n)
{
    if (n < maxn)
        return sphi[n];
    if (umsphi.count(n))
        return umsphi[n];
    ll ans = s3(n);
    for (ll l = 2, r; l <= n; l = r + 1)
    {
        r = n / (n / l);
        ans = (ans - (s2(r)-s2(l-1)+P)%P * sum_phi(n / l) % P + P) % P;
    }
    umsphi[n] = ans;
    return ans;
}
void solve() {
    cin >> P >> n;
    inv2 = power(2, P - 2);
    inv6 = power(6, P - 2);
    init(5e6);
    int ans = 0;
    for(int l = 1, r; l <= n; l = r + 1) {
        r = n / (n / l);
        ans = (ans + (sum_phi(r)-sum_phi(l-1)+P)%P * s3(n/l) % P) % P;
    }
    cout << ans << endl;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值