[hdu6428]Calculate(数论 欧拉函数 莫比乌斯反演)

题意

A,B,C1e7 A , B , C ≤ 1 e 7

i=1Aj=1Bk=1Cϕ(gcd(i,j2,k3)) ∑ i = 1 A ∑ j = 1 B ∑ k = 1 C ϕ ( g c d ( i , j 2 , k 3 ) )

题解

很难受 写这题的时候真是又困又难受,冷静下来细想并没有那么难qwq
学计算机果然要身体好才行呀

对于这个东西,我们先想到把 phi p h i gcd g c d 拆开。
f(d) f ( d ) 表示存在多少个 i,j,k i , j , k 使得 d|gcd(i,j2,k3) d | g c d ( i , j 2 , k 3 )
g(d) g ( d ) 表示存在多少个 i,j,k i , j , k 使得 d==gcd(i,j2,k3) d == g c d ( i , j 2 , k 3 )
我们先不考虑怎么求 f,g f , g

那么 ans=g(d)ϕ(d) a n s = ∑ g ( d ) ∗ ϕ ( d )

容易发现

f(d)=d|kg(k) f ( d ) = ∑ d | k g ( k )

然后我们莫比乌斯一下
g(d)=d|kμ(k/d)f(k) g ( d ) = ∑ d | k μ ( k / d ) ∗ f ( k )

再把这个带入 ans a n s

ans=ϕ(d)d|kf(k)μ(k/d) a n s = ∑ ϕ ( d ) ∗ ∑ d | k f ( k ) ∗ μ ( k / d )

=kf(k)d|kϕ(d)μ(k/d) = ∑ k f ( k ) ∑ d | k ϕ ( d ) ∗ μ ( k / d )

两个积性函数的狄利克雷卷积还是积性函数,后面这部分可以搞一搞线筛出来。
前面这一部分也好算 f(k)=AkBb[k]Cc[k] f ( k ) = A k ∗ B b [ k ] ∗ C c [ k ]
b[k]为最小的x使得 xx%k==0 x ∗ x % k == 0
c[k]同理
然后b[k],c[k]也是积性函数,线筛搞搞就可以了

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned int ui;
const int maxn = 1e7 + 10;
const int mod = 1<<30;
int prm[maxn], phi[maxn], tot; 
bool ok[maxn];

ui bb[maxn], cc[maxn], sx[maxn], fck[maxn];
void get_prime(int n){ 
tot = 0;
    memset(ok, 0, sizeof(ok)); phi[1] = 1;
    cc[1] = bb[1] = 1;
    sx[1] = 1;
    for (int i = 2; i <= n; i ++){
        if (!ok[i]){
            prm[++ tot] = i;
            phi[i] = i - 1;
            cc[i] = bb[i] = i;
            sx[i] = i - 2;
            fck[i] = i;
        }
        for (int j = 1; j <= tot; j ++){
            if (1LL * i * prm[j] > n) break;
            if (1LL * bb[i] * bb[i] % (i * prm[j]) == 0)
                bb[i * prm[j]] = bb[i];
            else bb[i * prm[j]] = bb[i] * prm[j];

            if (1LL * cc[i] * cc[i] % (i * prm[j]) * cc[i] % (i * prm[j]) == 0)
                cc[i * prm[j]] = cc[i];
            else cc[i * prm[j]] = cc[i] * prm[j];

            ok[i * prm[j]] = true;
            if (i % prm[j]){
                phi[i * prm[j]] = phi[i] * phi[prm[j]];
                sx[i * prm[j]] = sx[i] * sx[prm[j]];
                fck[i * prm[j]] = prm[j];
            }
            else{
                phi[i * prm[j]] = phi[i] * prm[j];
                sx[i * prm[j]] = sx[i / fck[i]] * (phi[fck[i] * prm[j]] - phi[fck[i]]);
                fck[i * prm[j]] = fck[i] * prm[j];          
                break;
            }
        }
    }
}

bool nsp[maxn];
void prepare(){
    get_prime(maxn - 1);
}
void work(){
    ui A,B,C;
    scanf("%u%u%u", &A, &B, &C);

    ui qwq = 0;
    for (int i = A; i; i --){
        qwq = qwq + 1LL * (A / i) * (B / bb[i]) * (C / cc[i]) * sx[i];
    }

    printf("%u\n", qwq % mod);
}
int main(){
    prepare();
    int T; scanf("%d", &T);
    while (T --)
        work();
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值