HDU - 5528 Count a * b (欧拉函数、除数函数)

题目vj链接

题面:
在这里插入图片描述

题意:
求解:
g ( m ) = ∑ m ∣ n f ( m ) , f ( m ) = ∑ a = 0 m − 1 ∑ b = 0 m − 1 [ a ∗ b % m ≠ 0 ] g(m)=\sum\limits_{m|n}f(m),f(m)=\sum\limits_{a=0}^{m-1}\sum\limits_{b=0}^{m-1}[a*b\%m\neq0] g(m)=mnf(m)f(m)=a=0m1b=0m1[ab%m=0]

题解:
①先化简 f ( m ) f(m) f(m)
f ( m ) = ∑ a = 0 m − 1 ∑ b = 0 m − 1 [ a ∗ b % m ≠ 0 ] f(m)=\sum\limits_{a=0}^{m-1}\sum\limits_{b=0}^{m-1}[a*b\%m\neq0] f(m)=a=0m1b=0m1[ab%m=0]

f ( m ) = m 2 − ∑ a = 0 m − 1 ∑ b = 0 m − 1 [ a ∗ b % m = 0 ] f(m)=m^2-\sum\limits_{a=0}^{m-1}\sum\limits_{b=0}^{m-1}[a*b\%m=0] f(m)=m2a=0m1b=0m1[ab%m=0]

f ( m ) = m 2 − ∑ a = 1 m ∑ b = 1 m [ a ∗ b % m = 0 ] f(m)=m^2-\sum\limits_{a=1}^{m}\sum\limits_{b=1}^{m}[a*b\%m=0] f(m)=m2a=1mb=1m[ab%m=0](a=0与a=m的贡献一致,b=0与b=m的贡献一致)

p ( m ) = ∑ a = 1 m ∑ b = 1 m [ a ∗ b % m = 0 ] p(m)=\sum\limits_{a=1}^{m}\sum\limits_{b=1}^{m}[a*b\%m=0] p(m)=a=1mb=1m[ab%m=0]

②求解 p ( m ) p(m) p(m)

p ( m ) = ∑ a = 1 m ∑ b = 1 m [ a ∗ b % m = 0 ] p(m)=\sum\limits_{a=1}^{m}\sum\limits_{b=1}^{m}[a*b\%m=0] p(m)=a=1mb=1m[ab%m=0]

= ∑ a = 1 m ∑ b = 1 m m ∣ ( a ∗ b ) =\sum\limits_{a=1}^{m}\sum\limits_{b=1}^{m}m|(a*b) =a=1mb=1mm(ab)

= ∑ a = 1 m ∑ b = 1 m m g c d ( m , a ) ∣ ( a g c d ( m , a ) ∗ b ) =\sum\limits_{a=1}^{m}\sum\limits_{b=1}^{m}\frac{m}{gcd(m,a)}|(\frac{a}{gcd(m,a)}*b) =a=1mb=1mgcd(m,a)m(gcd(m,a)ab)

= ∑ a = 1 m ∑ b = 1 m m g c d ( m , a ) ∣ b =\sum\limits_{a=1}^{m}\sum\limits_{b=1}^{m}\frac{m}{gcd(m,a)}|b =a=1mb=1mgcd(m,a)mb ,因为 g c d ( m g c d ( m , a ) , a g c d ( m , a ) ) = 1 gcd(\frac{m}{gcd(m,a)},\frac{a}{gcd(m,a)})=1 gcd(gcd(m,a)m,gcd(m,a)a)=1

= ∑ a = 1 m m m g c d ( a , m ) =\sum\limits_{a=1}^m\frac{m}{\frac{m}{gcd(a,m)}} =a=1mgcd(a,m)mm

= ∑ a = 1 m g c d ( a , m ) =\sum\limits_{a=1}^mgcd(a,m) =a=1mgcd(a,m)

= ∑ d = 1 m ∑ a = 1 m [ g c d ( a , m ) = d ] ∗ d =\sum\limits_{d=1}^m\sum\limits_{a=1}^m[gcd(a,m)=d]*d =d=1ma=1m[gcd(a,m)=d]d

= ∑ d ∣ m ∑ a = 1 m [ g c d ( a , m ) = d ] ∗ d =\sum\limits_{d|m}\sum\limits_{a=1}^m[gcd(a,m)=d]*d =dma=1m[gcd(a,m)=d]d

= ∑ d ∣ m d ∗ ∑ a = 1 m d [ g c d ( a , m d ) = 1 ] =\sum\limits_{d|m}d*\sum\limits_{a=1}^{\frac{m}{d}}[gcd(a,\frac{m}{d})=1] =dmda=1dm[gcd(a,dm)=1]

= ∑ d ∣ m d ∗ φ ( m d ) =\sum\limits_{d|m}d*\varphi(\frac{m}{d}) =dmdφ(dm)

③带入 g ( n ) g(n) g(n):
g ( m ) = ∑ m ∣ n f ( m ) g(m)=\sum\limits_{m|n}f(m) g(m)=mnf(m)

= ∑ m ∣ n ( m 2 − ∑ d ∣ m d ∗ φ ( m d ) ) =\sum\limits_{m|n}(m^2-\sum\limits_{d|m}d*\varphi(\frac{m}{d})) =mn(m2dmdφ(dm))

我们令 a ( n ) = ∑ m ∣ n m 2 ,   b ( n ) = ∑ m ∣ n ∑ d ∣ m d ∗ φ ( m d ) ,   g ( n ) = a ( n ) − b ( n ) a(n)=\sum\limits_{m|n}m^2,\space b(n)=\sum\limits_{m|n}\sum\limits_{d|m}d*\varphi(\frac{m}{d}),\space g(n)=a(n)-b(n) a(n)=mnm2, b(n)=mndmdφ(dm), g(n)=a(n)b(n)

④求解 a ( n ) a(n) a(n):

我们知道除数函数 σ ( k , x ) = ∑ d ∣ x d k \sigma(k,x)=\sum\limits_{d|x}d^k σ(k,x)=dxdk是积性函数,即若 g c d ( x , y ) = = 1 gcd(x,y)==1 gcd(x,y)==1,则 σ ( k , x ∗ y ) = σ ( k , x ) ∗ σ ( k , y ) \sigma(k,x*y)=\sigma(k,x)*\sigma(k,y) σ(k,xy)=σ(k,x)σ(k,y)

我们设 σ ( 2 , n ) = ∑ d ∣ n d 2 \sigma(2,n)=\sum\limits_{d|n}d^2 σ(2,n)=dnd2

将n唯一分解 n = p 1 e 1 ∗ p 2 e 2 ∗ . . . ∗ p k e k n=p_1^{e_1}*p_2^{e_2}*...*p_k^{e_k} n=p1e1p2e2...pkek
其中 ( p 1 e 1 , p 2 e 2 , . . . , p k e k ) (p_1^{e_1},p_2^{e_2},...,p_k^{e_k}) (p1e1,p2e2,...,pkek) 两两互质

σ ( 2 , n ) = σ ( 2 , p 1 e 1 ) ∗ σ ( 2 , p 2 e 2 ) ∗ . . . ∗ σ ( 2 , p k e k ) \sigma(2,n)=\sigma(2,p_1^{e_1})*\sigma(2,p_2^{e_2})*...*\sigma(2,p_k^{e_k}) σ(2,n)=σ(2,p1e1)σ(2,p2e2)...σ(2,pkek)

对于 σ ( 2 , p i e i ) = ( p i 0 ) 2 + ( p i 1 ) 2 + . . . + ( p i e i ) 2 \sigma(2,p_i^{e_i})=(p_i^0)^2+(p_i^1)^2+...+(p_i^{e_i})^2 σ(2,piei)=(pi0)2+(pi1)2+...+(piei)2

我们可以看作 a 1 = 1 , q = p i 2 a_1=1,q=p_i^2 a1=1,q=pi2 的等比数列求和。这样 O ( 1 ) O(1) O(1)即可求解。
因为这题要求对 2 64 2^{64} 264 取模,逆元不好处理,直接暴力计算即可。(因为 e i e_i ei不会很大)

⑤求解 b ( n ) b(n) b(n):
b ( n ) = ∑ m ∣ n ∑ d ∣ m d ∗ φ ( m d ) b(n)=\sum\limits_{m|n}\sum\limits_{d|m}d*\varphi(\frac{m}{d}) b(n)=mndmdφ(dm)

先枚举 d d d

b ( n ) = ∑ d ∣ n d ∗ ∑ d ∣ m , m ∣ n φ ( m d ) b(n)=\sum\limits_{d|n}d*\sum\limits_{d|m,m|n}\varphi(\frac{m}{d}) b(n)=dnddm,mnφ(dm)

= ∑ d ∣ n d ∗ ∑ ( k ∗ d ) ∣ n φ ( k ) =\sum\limits_{d|n}d*\sum\limits_{(k*d)|n}\varphi(k) =dnd(kd)nφ(k)

= ∑ d ∣ n d ∗ ∑ k ∣ n d φ ( k ) =\sum\limits_{d|n}d*\sum\limits_{k|\frac{n}{d}}\varphi(k) =dndkdnφ(k)

n n n 的因子的欧拉函数之和为 n n n

b ( n ) = ∑ d ∣ n d ∗ n d = ∑ d ∣ n n = n ∗ σ ( 0 , n ) = n ∗ ∏ ( e i + 1 ) b(n)=\sum\limits_{d|n}d*\frac{n}{d}=\sum\limits_{d|n}n=n*\sigma(0,n)=n*\prod(e_i+1) b(n)=dnddn=dnn=nσ(0,n)=n(ei+1)

⑥综上:
g ( n ) = σ ( 2 , n ) − n ∗ ∏ ( e i + 1 ) g(n)=\sigma(2,n)-n*\prod(e_i+1) g(n)=σ(2,n)n(ei+1)

时间复杂度 O ( T ∗ n ) O(T*\sqrt n) O(Tn )

代码:

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<string>
#include<queue>
#include<bitset>
#include<map>
#include<unordered_map>
#include<set>
#define ui unsigned int
#define ll long long
#define llu unsigned ll
#define ld long double
#define pr make_pair
#define pb push_back
#define lc (cnt<<1)
#define rc (cnt<<1|1)
#define len(x)  (t[(x)].r-t[(x)].l+1)
#define tmid ((l+r)>>1)
#define fhead(x) for(int i=head[(x)];i;i=nt[i])
#define max(x,y) ((x)>(y)?(x):(y))
#define min(x,y) ((x)>(y)?(y):(x))
using namespace std;

const int inf=0x3f3f3f3f;
const ll lnf=0x3f3f3f3f3f3f3f3f;
const double dnf=1e18;
const int mod=10007;
const double eps=1e-8;
const double pi=acos(-1.0);
const int hp=13331;
const int maxn=100100;
const int maxm=100100;
const int maxp=100100;
const int up=100100;

int prime[maxn],cnt=0;
bool ha[maxn];
int p[55],e[55],tot=0;

void Prime(void)
{
    ha[1]=true;
    for(int i=2;i<maxn;i++)
    {
        if(!ha[i])
            prime[++cnt]=i;
        for(int j=1;j<=cnt&&prime[j]*i<maxn;j++)
        {
            ha[i*prime[j]]=true;
            if(i%prime[j]==0) break;
        }
    }
}

void only(int n)
{
    memset(e,0,sizeof(e));
    tot=0;
    for(int i=1;prime[i]*prime[i]<=n;i++)
    {
        if(n%prime[i]) continue;
        p[++tot]=prime[i];
        while(n%prime[i]==0)
            e[tot]++,n/=prime[i];
    }
    if(n>1) p[++tot]=n,e[tot]=1;
}

int main(void)
{
    Prime();
    int tt,n;
    scanf("%d",&tt);
    while(tt--)
    {
        scanf("%d",&n);
        only(n);
        llu a=1,b=n;
        for(int i=1;i<=tot;i++)
        {
            b*=(e[i]+1);
            llu ans=1,pk=1;
            for(int j=1;j<=e[i];j++)
                pk=pk*p[i],ans=ans+pk*pk;
            a*=ans;
        }
        printf("%llu\n",a-b);
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值