HDU 6390 GuGuFishtion 莫比乌斯反演+欧拉函数性质

原题链接:http://acm.hdu.edu.cn/showproblem.php?pid=6390

题意

∑ a = 1 m ∑ b = 1 n G u ( a , b ) \sum_{a=1}^{m}\sum_{b=1}^{n}Gu(a,b) a=1mb=1nGu(a,b)
G u ( a , b ) = ϕ ( a b ) ϕ ( a ) ϕ ( b ) Gu(a,b)=\frac{\phi(ab)}{\phi(a)\phi(b)} Gu(a,b)=ϕ(a)ϕ(b)ϕ(ab)

化简

首 先 考 虑 对 G u 函 数 进 行 变 换 , 利 用 到 欧 拉 函 数 的 性 质 ϕ ( p k ) = ( p − 1 ) p k − 1 ( p 为 质 数 ) 首先考虑对Gu函数进行变换,利用到欧拉函数的性质\phi(p^k)=(p-1)p^{k-1}(p为质数) Guϕ(pk)=(p1)pk1(p)

G u ( a , b ) = ϕ ( p 1 2 k 1 p 2 2 k 2 . . p n 2 k n ) ϕ ( p 1 k 1 p 2 k 2 . . p n k n ) ϕ ( p 1 k 1 p 2 k 2 . . p n k n ) Gu(a,b)=\frac{\phi(p1^{2k1}p2^{2k2}..pn^{2kn})}{\phi(p1^{k1}p2^{k2}..pn^{kn})\phi(p1^{k1}p2^{k2}..pn^{kn})} Gu(a,b)=ϕ(p1k1p2k2..pnkn)ϕ(p1k1p2k2..pnkn)ϕ(p12k1p22k2..pn2kn)

= ( p 1 − 1 ) p 1 2 k 1 − 1 . . ( p n − 1 ) p n 2 k n − 1 ( p 1 − 1 ) 2 p 1 2 k 1 − 2 . . ( p n − 1 ) 2 p n 2 k n − 2 =\frac{(p1-1)p1^{2k1-1}..(pn-1)pn^{2kn-1}}{(p1-1)^2p1^{2k1-2}..(pn-1)^2pn^{2kn-2}} =(p11)2p12k12..(pn1)2pn2kn2(p11)p12k11..(pn1)pn2kn1

= p 1 p 2.. p n ( p 1 − 1 ) ( p 2 − 1 ) . . ( p n − 1 ) =\frac{p1p2..pn}{(p1-1)(p2-1)..(pn-1)} =(p11)(p21)..(pn1)p1p2..pn

= p 1 p 2.. p n ϕ ( p 1 p 2.. p n ) =\frac{p1p2..pn}{\phi(p1p2..pn)} =ϕ(p1p2..pn)p1p2..pn

= g c d ( a , b ) ϕ ( g c d ( a , b ) ) =\frac{gcd(a,b)}{\phi(gcd(a,b))} =ϕ(gcd(a,b))gcd(a,b)

接 下 来 就 是 熟 悉 的 模 型 接下来就是熟悉的模型

∑ a = 1 m ∑ b = 1 n G u ( a , b ) \sum_{a=1}^{m}\sum_{b=1}^{n}Gu(a,b) a=1mb=1nGu(a,b)

= ∑ a = 1 m ∑ b = 1 n g c d ( a , b ) ϕ ( g c d ( a , b ) ) =\sum_{a=1}^{m}\sum_{b=1}^{n}\frac{gcd(a,b)}{\phi(gcd(a,b))} =a=1mb=1nϕ(gcd(a,b))gcd(a,b)

设 g c d ( a , b ) = d 设gcd(a,b)=d gcd(a,b)=d

= ∑ d = 1 m i n ( n , m ) d ϕ ( d ) ∑ a = 1 m ∑ b = 1 n [ g c d ( a , b ) = d ] =\sum_{d=1}^{min(n,m)}\frac{d}{\phi(d)}\sum_{a=1}^{m}\sum_{b=1}^{n}[gcd(a,b)=d] =d=1min(n,m)ϕ(d)da=1mb=1n[gcd(a,b)=d]

= ∑ d = 1 m i n ( n , m ) d ϕ ( d ) ∑ a = 1 m / d ∑ b = 1 n / d ∑ t ∣ a , t ∣ b μ ( t ) =\sum_{d=1}^{min(n,m)}\frac{d}{\phi(d)}\sum_{a=1}^{m/d}\sum_{b=1}^{n/d}\sum_{t|a,t|b}\mu(t) =d=1min(n,m)ϕ(d)da=1m/db=1n/dta,tbμ(t)

= ∑ d = 1 m i n ( n , m ) d ϕ ( d ) ∑ t = 1 m i n ( n , m ) / d μ ( t ) ∑ a = 1 m / t d ∑ b = 1 n / t d =\sum_{d=1}^{min(n,m)}\frac{d}{\phi(d)}\sum_{t=1}^{min(n,m)/d}\mu(t)\sum_{a=1}^{m/td}\sum_{b=1}^{n/td} =d=1min(n,m)ϕ(d)dt=1min(n,m)/dμ(t)a=1m/tdb=1n/td

= ∑ d = 1 m i n ( n , m ) d ϕ ( d ) ∑ t = 1 m i n ( n , m ) / d μ ( t ) [ m t d ] [ n t d ] =\sum_{d=1}^{min(n,m)}\frac{d}{\phi(d)}\sum_{t=1}^{min(n,m)/d}\mu(t)[\frac{m}{td}][\frac{n}{td}] =d=1min(n,m)ϕ(d)dt=1min(n,m)/dμ(t)[tdm][tdn]

设 f ( n , m ) = ∑ i = 1 m i n ( n , m ) μ ( t ) [ m i ] [ n i ] 设f(n,m)=\sum_{i=1}^{min(n,m)}\mu(t)[\frac{m}{i}][\frac{n}{i}] f(n,m)=i=1min(n,m)μ(t)[im][in]

f ( n , m ) 用 整 除 分 块 可 以 在 ( n ) 的 时 间 复 杂 里 完 成 f(n,m)用整除分块可以在\sqrt(n)的时间复杂里完成 f(n,m)( n)

原 式 = ∑ d = 1 m i n ( n , m ) d ϕ ( d ) f ( n d , m d ) 原式=\sum_{d=1}^{min(n,m)}\frac{d}{\phi(d)}f(\frac{n}{d},\frac{m}{d}) =d=1min(n,m)ϕ(d)df(dn,dm)

因 为 ϕ ( d ) < d , 因 此 用 线 性 求 一 下 逆 元 , 那 么 总 的 时 间 复 杂 度 就 是 O ( n l o g n ) 因为\phi(d)<d,因此用线性求一下逆元,那么总的时间复杂度就是O(nlogn) ϕ(d)<d线O(nlogn)

Code

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <cmath>
#include <bitset>
#include <map>
#include <set>
#include <stack>
#include <queue>
//#include <unordered_map>
using namespace std;
#define fi first
#define se second
#define re register
typedef long long ll;
typedef pair<ll, ll> PII;
typedef unsigned long long ull;
const int N = 1e6 + 10, M = 1e6 + 5, INF = 0x3f3f3f3f;
const int MOD = 1e9 + 7;
ll prime[N], mu[N], k, p;
ll phi[N], inv[N];
bool is_prime[N];
void get_inv(int n) {  //线性递推
    inv[1] = 1;
    for(int i = 2; i < n; i++)
        inv[i] = 1ll*(p - p / i) * inv[p % i] % p;
}
inline void init(int n) {
    memset(is_prime, true, sizeof is_prime);
    mu[1] = 1; phi[1] = 1;
    for (int i = 2; i < n; ++i) {
        if (is_prime[i]) prime[++k] = i, mu[i] = -1, phi[i] = i-1;
        for (int j = 1; j <= k && i * prime[j] < n; ++j) {
            is_prime[i * prime[j]] = false;
            if (i % prime[j] == 0) {
                phi[i * prime[j]] = phi[i] * prime[j];
                break;
            } else {
                mu[i * prime[j]] = -mu[i];
                phi[i * prime[j]] = phi[i] * (prime[j] - 1);
            }
        }
    }
    for (int i = 1; i < n; ++i) mu[i] += mu[i-1];
}
ll calc(ll n, ll m) {
    ll ans = 0;
    for (ll l = 1, r; l <= min(n, m); l = r + 1) {
        r = min(m / (m / l), n / (n / l));
        ans = (ans + (mu[r] - mu[l-1] + p) % p * (n / l) % p * (m / l) % p) % p;
    }
    return ans;
}
void solve() {
    init(N);
    int T; cin >> T; while (T--) {
        int m, n; cin >> m >> n >> p;
        get_inv(min(n, m));
        ll ans = 0;
        for (int i = 1; i <= min(n, m); i++) ans = (ans + i * inv[phi[i]] % p * calc(n/i, m/i) % p) % p;
        cout << ans << endl;
    }
}

signed main() {
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
#ifdef ACM_LOCAL
    freopen("input", "r", stdin);
    freopen("output", "w", stdout);
#endif
    solve();
    return 0;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值