HDU5528 Count a*b 数论函数前缀和

Description

定义 f ( m ) = ∑ i = 0 m − 1 ∑ j = 0 m − 1 [ g c d ( m , i ∗ j ) ≠ m ] f(m) = \sum^{m-1}_{i=0}\sum^{m-1}_{j=0}[gcd(m,i*j) \ne m] f(m)=i=0m1j=0m1[gcd(m,ij)̸=m]
g ( n ) = ∑ m ∣ n f ( m ) g(n) = \sum_{m|n}f(m) g(n)=mnf(m)


Input

The first line contains an integer T T T indicating the total number of test cases. Each test case is a line with a positive integer n n n.
1 ≤ T ≤ 20000 1\leq T\leq 20000 1T20000
1 ≤ n ≤ 1 0 9 1\leq n\leq 10^9 1n109


Output

For each test case, print one integer s s s, representing g ( n ) g(n) g(n) modulo 2 64 2^{64} 264.


Solution

考虑 f ( x ) f(x) f(x)的反面 h ( x ) h(x) h(x)
f ( m ) = m 2 − h ( m ) f(m) = m^2- h(m) f(m)=m2h(m)
h ( m ) = ∑ i = 0 m − 1 ∑ j = 0 m − 1 [ g c d ( m , i ∗ j ) = m ] h(m) = \sum^{m-1}_{i=0}\sum^{m-1}_{j=0}[gcd(m,i*j) = m] h(m)=i=0m1j=0m1[gcd(m,ij)=m]
那么对于 h ( x ) h(x) h(x)进行变化。
考虑 i , j i,j i,j的所有取值情况,在满足 g c d ( m , i j ) = m gcd(m,ij) = m gcd(m,ij)=m的情况下二元组 ( i , j ) (i,j) (i,j)有多少种。


我们考虑枚举 m m m的所有因子 d d d
如果 g c d ( m , i ) = d gcd(m,i) = d gcd(m,i)=d,则要使得满足条件 g c d ( m , i j ) = m gcd(m,ij) = m gcd(m,ij)=m j j j需要满足条件 m d ∣ j \frac{m}{d}|j dmj
因为这样 j j j中包含了 m d \frac{m}{d} dm,相乘后 i j ij ij中才能包含 m m m,也就是 m ∣ i j m|ij mij
以上也就是说满足 d ∣ i , m d ∣ j d|i,\frac{m}{d}|j di,dmj时有 m ∣ i j m|ij mij,则 g c d ( m , i j ) = m gcd(m,ij)=m gcd(m,ij)=m


那么对于 i i i 0 ≤ i < m 0\leq i <m 0i<m g c d ( m , i ) = d gcd(m,i) = d gcd(m,i)=d
i i i取值可以为 k ∗ d ( 1 ≤ k ≤ m d ) k*d(1 \leq k \leq \frac{m}{d}) kd(1kdm),因为有 d ∣ i d|i di,所以 i = k ∗ d i = k*d i=kd
要满足
g c d ( m , i ) = d gcd(m,i) = d gcd(m,i)=d
g c d ( m , k ∗ d ) = d gcd(m,k*d)=d gcd(m,kd)=d
g c d ( m d , k ) = 1 gcd(\frac{m}{d},k) = 1 gcd(dm,k)=1
于是 k k k的取值个数为 φ ( m d ) \varphi(\frac{m}{d}) φ(dm),这也是 i i i的取值个数。


接下来考虑在满足上述条件下的 j j j的所有可能取值。
m d ∣ j ( 0 ≤ j < m ) \frac{m}{d}|j\qquad(0\leq j < m) dmj(0j<m)
则可以写成
j = k ∗ m d j = k * \frac{m}{d} j=kdm
于是
[ k ] = m m d = d [k]= \frac{m}{\frac{m}{d}} = d [k]=dmm=d
于是 k k k的取值个数为 d d d,这也是 j j j的取值个数。


综上我们得到 h ( m ) h(m) h(m) f ( m ) f(m) f(m)的表达式
h ( m ) = ∑ d ∣ m d ∗ φ ( m d ) h(m) =\sum_{d|m}d*\varphi(\frac{m}{d}) h(m)=dmdφ(dm)
f ( m ) = m 2 − h ( m ) = m 2 − ∑ d ∣ m d ∗ φ ( m d ) f(m) =m^2 - h(m) = m^2 - \sum_{d|m}d*\varphi(\frac{m}{d}) f(m)=m2h(m)=m2dmdφ(dm)


那么接下来是 g ( n ) g(n) g(n)
g ( n ) = ∑ m ∣ n f ( m ) g(n) = \sum_{m|n}f(m) g(n)=mnf(m)
g ( n ) = ∑ m ∣ n m 2 − ∑ m ∣ n ∑ d ∣ m d ∗ φ ( m d ) g(n) = \sum_{m|n}m^2-\sum_{m|n}\sum_{d|m}d*\varphi(\frac{m}{d}) g(n)=mnm2mndmdφ(dm)

g 1 ( n ) = ∑ m ∣ n m 2 g 2 ( n ) = ∑ m ∣ n ∑ d ∣ m d ∗ φ ( m d ) g_1(n) = \sum_{m|n}m^2 \qquad g_2(n)=\sum_{m|n}\sum_{d|m}d*\varphi(\frac{m}{d}) g1(n)=mnm2g2(n)=mndmdφ(dm)
可以发现的是 g 1 ( n ) g_1(n) g1(n) g 2 ( n ) g_2(n) g2(n)都是积性函数 (不是完全积性函数)。
那么满足 g ( n ) = ∏ i = 0 c g ( p i k i ) n = p 0 k 0 . p 1 k 1 . . . p c k c g(n) = \prod_{i=0}^{c}{g(p_i^{k_i})}\quad n=p_0^{k_0}.p_1^{k_1}...p_{c}^{k_{c}} g(n)=i=0cg(piki)n=p0k0.p1k1...pckc
g 1 ( n ) = ∏ i = 0 c g 1 ( p i k i ) g_1(n) = \prod _{i=0}^{c}g_1(p_i^{k_i}) g1(n)=i=0cg1(piki)
g 2 ( n ) = ∏ i = 0 c g 2 ( p i k i ) g_2(n) = \prod_{i=0}^{c}g_2(p_i^{k_i}) g2(n)=i=0cg2(piki)


其实对于求解 g ( p k ) g(p^k) g(pk)就变得简单了。
因为 p k p^k pk只有 k + 1 k+1 k+1个因子 p 0 , p 1 , p 2 , . . . , p k p^0,p^1,p^2,...,p^k p0,p1,p2,...,pk
于是只有分解质因数的复杂度了。
g 1 ( p k ) = ∑ m ∣ n m 2 = ∑ i = 0 k ( p 2 i ) g_1(p^k) =\sum_{m|n}m^2 =\sum_{i=0}^{k}(p^{2i}) g1(pk)=mnm2=i=0k(p2i)
g 2 ( p k ) = ∑ m ∣ n ∑ d ∣ m d ∗ φ ( m d ) = ∑ i = 0 k [ p i + ∑ j = 1 i ( p j − p j − 1 ) ∗ p i − j ] g_2(p^k) = \sum_{m|n}\sum_{d|m}d*\varphi(\frac{m}{d}) = \sum_{i=0}^{k}[p^i+\sum_{j=1}^{i}(p^j-p^{j-1})*p^{i-j}] g2(pk)=mndmdφ(dm)=i=0k[pi+j=1i(pjpj1)pij]
注: φ ( p k ) = p k − p k − 1 \color{red}\varphi(p^k) = p^k - p^{k-1} φ(pk)=pkpk1,上式子读者可手推便可以发现。
= ∑ i = 0 k p i + ∑ i = 0 k ∑ j = 1 i ( p − 1 ) ∗ p j − 1 ∗ p i − j =\sum_{i=0}^{k}p^i+\sum_{i=0}^{k}\sum_{j=1}^{i}(p-1)*p^{j-1}*p^{i-j} =i=0kpi+i=0kj=1i(p1)pj1pij
= ∑ i = 0 k p i + ∑ i = 0 k ∑ j = 1 i ( p − 1 ) ∗ p i − 1 =\sum_{i=0}^{k}p^i+\sum_{i=0}^{k}\sum_{j=1}^{i}(p-1)*p^{i-1} =i=0kpi+i=0kj=1i(p1)pi1
= ∑ i = 0 k p i + ∑ i = 0 k i ∗ ( p − 1 ) ∗ p i − 1 =\sum_{i=0}^{k}p^i+\sum_{i=0}^{k}i*(p-1)*p^{i-1} =i=0kpi+i=0ki(p1)pi1
= ∑ i = 0 k p i + p − 1 p ∑ i = 0 k i ∗ p i =\sum_{i=0}^{k}p^i+\frac{p-1}{p}\sum_{i=0}^{k}i*p^i =i=0kpi+pp1i=0kipi
= ∑ i = 0 k p i + ∑ i = 0 k i ∗ p i − ∑ i = 0 k i ∗ p i − 1 =\sum_{i=0}^{k}p^i+\sum_{i=0}^{k}i*p^i-\sum_{i=0}^{k}i*p^{i-1} =i=0kpi+i=0kipii=0kipi1
= ∑ i = 0 k ( i + 1 ) ∗ p i − ∑ i = 0 k i ∗ p i − 1 =\sum_{i=0}^{k}(i+1)*p^i-\sum_{i=0}^{k}i*p^{i-1} =i=0k(i+1)pii=0kipi1
= ∑ i = 1 k + 1 i ∗ p i − 1 − ∑ i = 0 k i ∗ p i − 1 =\sum_{i=1}^{k+1}i*p^{i-1}-\sum_{i=0}^{k}i*p^{i-1} =i=1k+1ipi1i=0kipi1
= ( k + 1 ) ∗ p k − 0 = ( k + 1 ) ∗ p k =(k+1)*p^k-0 = (k+1)*p^k =(k+1)pk0=(k+1)pk


综上
g 1 ( n ) = ∏ i = 0 c g 1 ( p i k i ) = ∏ i = 0 c ∑ j = 0 k i ( p i 2 j ) g_1(n) = \prod_{i=0}^{c}g_1(p_i^{k_i})=\prod_{i=0}^{c}\sum_{j=0}^{k_i}(p_{i}^{2j}) g1(n)=i=0cg1(piki)=i=0cj=0ki(pi2j)
g 2 ( n ) = ∏ i = 0 c g 2 ( p i k i ) = ∏ i = 0 c ( k i + 1 ) p i k i g_2(n) = \prod_{i=0}^{c}g_2(p_i^{k_i}) =\prod_{i=0}^{c}(k_i+1)p_i^{k_i} g2(n)=i=0cg2(piki)=i=0c(ki+1)piki


Code

#include
using namespace std;
const int maxn = 1e5+10;
typedef unsigned long long ll;
int prime[maxn];
inline void getPrime() {
    memset(prime,0,sizeof(prime));
    prime[1] = 1;
    for(int i=2;i<maxn;i++) {
        if(!prime[i]) prime[++prime[0]] = i; 
        for(int j=1;j<=prime[0] && prime[j]*i < maxn;j++) {
            prime[prime[j]*i] = 1;
            if(i % prime[j] == 0) break;
        }
    }
}
void getFactors(int x) {
    int tmp = x;
    ll res = 1,ans = 1;
    for(int i=1;i<=prime[0]&&prime[i]*prime[i]<=tmp;i++) {
        if(tmp % prime[i] == 0) {
            ll t1 = 1,t2 = 0,p = 1;
            while(tmp % prime[i] == 0) {
                tmp /= prime[i];
                p = p * prime[i];
                t1 = t1 + p * p;
                t2++;
            }
            //printf("%llu %llu\n",t1,t2);
            res = res * t1;
            ans = ans * (t2 + 1) * p;
        }
    }
    if(tmp != 1) {
        res = res * ((ll)tmp * tmp + 1);
        ans = ans * ((ll)2*tmp);
    }
    printf("%llu\n",res - ans);
}

int main()
{
    getPrime();
    int caset;scanf("%d",&caset);
    int n;
    while(caset--) {
        scanf("%d",&n);
        getFactors(n);
    }
    return 0;
}

你可能感兴趣的:(数论)