Count a * b(欧拉函数,唯一分解定理)

Count a * b

题意:有 t t t组输入,每组输入入一个数 n ( n ≤ 1 0 9 ) n(n\leq 10^9) n(n109),求 g ( n ) = ∑ m ∣ n f ( m ) g(n) = \sum_{m|n}f(m) g(n)=mnf(m) f ( m ) = ∑ i = 0 m − 1 ∑ j = 0 m − 1 [ i × j % m ≠ 0 ] f(m)=\sum_{i=0}^{m-1}\sum_{j=0}^{m-1}[i\times j \%m \neq 0] f(m)=i=0m1j=0m1[i×j%m=0]

推式子:
f ( m ) = ∑ i = 0 m − 1 ∑ j = 0 m − 1 [ i × j   %   m ≠ 0 ] = ∑ i = 1 m ∑ j = 1 m [ i × j   %   m ≠ 0 ] = m 2 − ∑ i = 1 m ∑ j = 1 m [ i × j   %   m = 0 ] = m 2 − ∑ i = 1 m ∑ j = 1 m [ m ∣ i × j ] = m 2 − ∑ i = 1 m ∑ j = 1 m [ m g c d ( i , m ) ∣ i g c d ( i , m ) × j ] = m 2 − ∑ i = 1 m m m g c d ( i , m ) = m 2 − ∑ i = 1 m g c d ( i , m ) = m 2 − ∑ d ∣ m ∑ i = 1 m [ g c d ( i , m ) = d ] = m 2 − ∑ d ∣ m d ∑ i = 1 m d [ g c d ( i , m d ) = 1 ] = m 2 − ∑ d ∣ m d ϕ ( m d ) f(m)=\sum_{i=0}^{m-1}\sum_{j=0}^{m-1}[i\times j ~\%~m \neq 0]\\ =\sum_{i=1}^m\sum_{j=1}^m[i\times j ~\%~ m \neq0]\\ =m^2-\sum_{i=1}^m\sum_{j=1}^m[i\times j ~\%~ m =0]\\ =m^2-\sum_{i=1}^m\sum_{j=1}^m[m|i\times j]\\ =m^2-\sum_{i=1}^m\sum_{j=1}^m[\frac m{gcd(i,m)}|\frac i{gcd(i,m)}\times j]\\ =m^2-\sum_{i=1}^m\frac m{\frac m {gcd(i, m)}}\\ =m^2-\sum_{i=1}^mgcd(i,m)\\ =m^2-\sum_{d|m}\sum_{i=1}^m[gcd(i,m)=d]\\ =m^2-\sum_{d|m}d\sum_{i=1}^{\frac md}[gcd(i, \frac md)=1]\\ =m^2-\sum_{d|m}d\phi(\frac md)\\ f(m)=i=0m1j=0m1[i×j % m=0]=i=1mj=1m[i×j % m=0]=m2i=1mj=1m[i×j % m=0]=m2i=1mj=1m[mi×j]=m2i=1mj=1m[gcd(i,m)mgcd(i,m)i×j]=m2i=1mgcd(i,m)mm=m2i=1mgcd(i,m)=m2dmi=1m[gcd(i,m)=d]=m2dmdi=1dm[gcd(i,dm)=1]=m2dmdϕ(dm)
1. ∑ i = 0 m − 1 ∑ j = 0 m − 1 [ i × j   %   m ≠ 0 ] = ∑ i = 1 m ∑ j = 1 m [ i × j   %   m ≠ 0 ] \sum_{i=0}^{m-1}\sum_{j=0}^{m-1}[i\times j ~\%~m \neq 0] =\sum_{i=1}^m\sum_{j=1}^m[i\times j ~\%~ m \neq0] i=0m1j=0m1[i×j % m=0]=i=1mj=1m[i×j % m=0]

i = 0 i=0 i=0 i = n i=n i=n的时候, i × j % m = 0 i\times j\%m=0 i×j%m=0,同样 j = 0 j=0 j=0 j = 1 j=1 j=1的时候 i × j % m = 0 i\times j\%m=0 i×j%m=0

2. ∑ i = 1 m ∑ j = 1 m [ m g c d ( i , m ) ∣ i g c d ( i , m ) × j ] = ∑ i = 1 m m m g c d ( i , m ) \sum_{i=1}^m\sum_{j=1}^m[\frac m{gcd(i,m)}|\frac i{gcd(i,m)}\times j] =\sum_{i=1}^m\frac m{\frac m {gcd(i, m)}} i=1mj=1m[gcd(i,m)mgcd(i,m)i×j]=i=1mgcd(i,m)mm.

m g c d ( i , m ) \frac m{gcd(i, m)} gcd(i,m)m i g c d ( i , m ) \frac i {gcd(i,m)} gcd(i,m)i是互质的,所以 ∑ i = 1 m ∑ j = 1 m [ m g c d ( i , m ) ∣ i g c d ( i , m ) × j ] = ∑ i = 1 m ∑ j = 1 m [ m g c d ( i , m ) ∣ j ] \sum_{i=1}^m\sum_{j=1}^m[\frac m{gcd(i,m)}|\frac i{gcd(i,m)}\times j]=\sum_{i=1}^m\sum_{j=1}^m[\frac m{gcd(i,m)}|j] i=1mj=1m[gcd(i,m)mgcd(i,m)i×j]=i=1mj=1m[gcd(i,m)mj],等价于在区间[1,m]中有多少个 m g c d ( i , m ) \frac m {gcd(i,m)} gcd(i,m)m的倍数,就是 m m g c d ( i , m ) \frac m{\frac m {gcd(i, m)}} gcd(i,m)mm

g ( n ) = ∑ m ∣ n f ( m ) = ∑ m ∣ n m 2 − ∑ m ∣ n ∑ d ∣ m d ϕ ( m d ) = ∑ m ∣ n m 2 − ∑ d ∣ n d ∑ m ∣ n , d ∣ m ϕ ( m d ) = ∑ m ∣ n m 2 − ∑ d ∣ n d ∑ k ∣ n d ϕ ( k ) = ∑ m ∣ n m 2 − ∑ d ∣ n n g(n) = \sum_{m|n}f(m)\\ =\sum_{m|n}m^2-\sum_{m|n}\sum_{d|m}d\phi(\frac md)\\ =\sum_{m|n}m^2-\sum_{d|n}d\sum_{m|n,d|m}\phi(\frac md)\\ =\sum_{m|n}m^2-\sum_{d|n}d\sum_{k|\frac nd}\phi(k)\\ =\sum_{m|n}m^2-\sum_{d|n}n g(n)=mnf(m)=mnm2mndmdϕ(dm)=mnm2dndmn,dmϕ(dm)=mnm2dndkdnϕ(k)=mnm2dnn

1. ∑ m ∣ n ∑ d ∣ m d ϕ ( m d ) = ∑ d ∣ n d ∑ m ∣ n , d ∣ m ϕ ( m d ) = ∑ d ∣ n d ∑ k ∣ n d ϕ ( k ) \sum_{m|n}\sum_{d|m}d\phi(\frac md)=\sum_{d|n}d\sum_{m|n,d|m}\phi(\frac md)=\sum_{d|n}d\sum_{k|\frac nd}\phi(k) mndmdϕ(dm)=dndmn,dmϕ(dm)=dndkdnϕ(k)

我们把d提出去,d是m的因子,m是n的因子,所以d是n的因子。

m是n的因子,d是m的因子,我们从m和n中都提出一个d,就可以得到 m d \frac md dm n d \frac nd dn的因子。

思路:

1.考虑暴力: t ≤ 20000 , n ≤ 1 0 9 t\leq 20000,n\leq 10^9 t20000n109,枚举全部的因子 O ( t n ) O(t\sqrt n) O(tn )复杂度太高。

2.唯一分解定理: x = ∏ i = 1 k p i e i x=\prod_{i=1}^{k}p_i^{e_i} x=i=1kpiei

​ x的因子个数= ∏ i = 1 k ( e i + 1 ) \prod_{i=1}^k(e_i+1) i=1k(ei+1)

​ x的因子和= ∏ i = 1 k ( 1 + p i 1 + p i 2 . . . p i e i ) \prod_{i=1}^k(1+p_i^1+p_i^2...p_i^{e_i}) i=1k(1+pi1+pi2...piei)

​ x的因子平方和= ∏ i = 1 k ( 1 + p i 2 + p i 4 . . . p i 2 e i ) \prod_{i=1}^k(1+p_i^2+p_i^4...p_i^{2e_i}) i=1k(1+pi2+pi4...pi2ei)

C o d e Code Code

#include<bits/stdc++.h>
using namespace std;
typedef unsigned long long ull;
const int N = 1e5+10;
ull p[N], tot;
bool st[N];
//初始化求欧拉函数。
void init() {
    for(int i=2; i<N; i++) {
        if(!st[i]) p[tot++] = i;
        for(int j=0; j<tot&&i*p[j]<N; j++) {
            st[i*p[j]] = 1;
            if(i % p[j] == 0) break;
        }
    }
}
//快速幂
ull qpow(ull x, int y) {
    ull ans = 1;
    while(y) {
        if(y & 1) ans = ans * x;
        x = x * x;
        y >>= 1;
    }
    return ans;
}
int main() {
#ifndef ONLINE_JUDGE
    freopen("in.txt", "r", stdin);
    freopen("out.txt", "w", stdout);
#endif
    init();
    int t;
    cin >> t;
    while(t--) {
        //ans表示n的因子平方和,sum表示n的因子个数。
        ull n, m, ans = 1, sum = 1;
        scanf("%llu", &n);
        m = n;
        //分解质因子
        for(int i=0; i<tot&&p[i]*p[i]<=n; i++) {
            if(n % p[i]) continue;//不是n的因子
            ull k = 0;
            while(n % p[i] == 0) k++, n /= p[i];
            //等差数列求和
            ull res = 1+p[i]*p[i]*((qpow(p[i],2*k)-1)/(p[i]*p[i]-1));
            
            ans *= res;
            sum *= (k+1);
        }
        //判断n是否全部分解。
        if(n > 1) {
            ans *= 1ull+n*n;
            sum *= 2ull;
        }
        printf("%llu\n", ans-sum*m);
    }
    return 0;
}
  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值