1. 程式人生 > >HDU 6428 2018HDU多校賽 第十場 Calculate(莫比烏斯反演 + 積性 + 線性篩)

HDU 6428 2018HDU多校賽 第十場 Calculate(莫比烏斯反演 + 積性 + 線性篩)

題意簡單粗暴,讓你求  \large \sum_{i=1}^{A}\sum_{j=1}^{B}\sum_{k=1}^{C}\phi(gcd(i,j^2,k^3))\ mod\ 2^{30}

與gcd有關,一般來說都是要上莫比烏斯來反演一下了。具體來說,我們先來推一些式子:

                                              \large \begin{align*} \phi(n) &=\sum_{d|n}\mu(d)(n/d) \\ &= \sum_{d|n}\mu(d)\sum_{d'|n/d}\phi(d') \\ &= \sum_{dd'|n}\mu(d)\phi(d') \\ &= \sum_{d|n}\sum_{d'|d}\mu(d')\phi(d/d') \\ &= \sum_{d|n} (\mu*\phi)(d) \end{align*}

那麼,原式我們就可以寫成:\large \sum_{i=1}^{A}\sum_{j=1}^{B}\sum_{k=1}^{C}\sum_{d|i,d|j^2,d|k^3}(\mu*\phi)(d)\ mod\ 2^{30}

然後我們再交換一下求和次序:\large \sum_{d=1}^{A}(\mu*\phi)(d)\sum_{i=1,d|i}^{A}\sum_{j=1,d|j^2}^{B}\sum_{k=1,d|k^3}^{C}1\ mod\ 2^{30}

對於後面這個東西,我們可以發現,對於一個數字x^k,他能夠被d整除,當且僅當\large pi^{\lceil\frac{ai}{k}\rceil}|x,其中pi表示d分解質因子的每一個數字,ai表示對應pi的指數。那麼我麼令\large f_{k}(i)=\prod_{i=1}^{n}pi^{\lceil\frac{ai}{k}\rceil},那麼最後的答案就是:

                          \large ans=\sum_{d=1}^{A}(\mu*\phi)(d)\lfloor\frac{A}{f_1(d)}\rfloor\lfloor\frac{B}{f_2(d)}\rfloor\lfloor\frac{C}{f_3(d)}\rfloor\ mod\ 2^{30}

我們注意到,\large (\mu*\phi)(d)是尤拉函式和莫比烏斯函式的迪利克雷卷積,根據定理,積性函式的迪利克雷卷積也是積性函式,因此\large (\mu*\phi)(d)

具有積性。而\large f_1(d)\large f_2(d)\large f_3(d)是類似於d分解質因子的形式,顯然也是具有積性的,因此我們可以構造線性篩,在O(A)的時間複雜度內解決這道題。所謂積性,就是在互質的時候f(xy)=f(x)*f(y),關鍵是要求不互質的時候以及質數本身的表示式。

我們令\large h(d)= (\mu*\phi)(d),根據我們之前的推導:\large \phi(n)=\sum_{d|n} h(d),那麼有:

                                                    \large \phi(p^n)=\phi(p^{n-1})+h(p^n)

於是:                                         \large \begin{align*} h(p^n)&=\phi(p^n)-\phi(p^{n-1}) \\ &= (p-1)p^{n-1}-(p-1)p^{n-2} \\ &= (p-1)(p^{n-1}-p^{n-2}) \\ &=(p-1)p^{n-2}(p-1) \\ &=(p-1)^2p^{n-2} \end{align*}

那麼:                                    \large \begin{align*}h(1) &= 1 \\ h(p) &= p-2 \\ h(p^n) &= (p-1)^2p^{n-2} \\ h(p_1^{n_1}p_2^{n_2})&=h(p_1^{n_1})h(p_2^{n_2}) \\ &... \\ &... \end{align*}

接下來再看這個\large f_k(n),這個就是在分解質因子的過程中,記錄一個deg,表示當前質因子的指數。每次這個質因子加一,當發現它%k之後是1,說明此時除以k向上取整會變大,於是\large f_k(n)

乘上當前質因子。具體見程式碼:

#include<bits/stdc++.h>
#define LL long long
#define mod 998244353
#define pb push_back
#define lb lower_bound
#define ub upper_bound
#define INF 0x3f3f3f3f
#define sf(x) scanf("%d",&x)
#define sc(x,y,z) scanf("%d%d%d",&x,&y,&z)
#define clr(x,n) memset(x,0,sizeof(x[0])*(n+5))
#define file(x) freopen(#x".in","r",stdin),freopen(#x".out","w",stdout)

using namespace std;

const int N = 1e7 + 10;

unsigned int p[N],phmu[N],f2[N],f3[N],last[N],deg[N];
bool isp[N];

void init()
{
    int sz=0;
    phmu[1]=f2[1]=f3[1]=last[N]=1;
    for(int i=2;i<N;i++)
    {
        if(!isp[i])
        {
            f2[i]=f3[i]=p[++sz]=i;
            phmu[i]=i-2; last[i]=deg[i]=1;
        }
        for(int j=1;j<=sz&&(LL)i*p[j]<N;j++)
        {
            int x=i*p[j];
            isp[x]=1;
            if(i%p[j]==0)
            {
                last[x]=last[i];
                deg[x]=deg[i]+1;
                if (last[i]>1) phmu[x]=phmu[last[i]]*phmu[x/last[i]];
                else
                {
                    if (i>p[j]) phmu[x]=phmu[i]*p[j];
                        else phmu[x]=(p[j]-1)*(p[j]-1);
                }
                f2[x]=f2[i]*(deg[x]%2==1?p[j]:1);
                f3[x]=f3[i]*(deg[x]%3==1?p[j]:1);
                break;
            } else
            {
                deg[x]=1;
                last[x]=i;
                f2[x]=f2[i]*f2[p[j]];
                f3[x]=f3[i]*f3[p[j]];
                phmu[x]=phmu[i]*phmu[p[j]];
            }
        }
    }

}

int main()
{
    init();
    int T; sf(T);
    while(T--)
    {
        int a,b,c;
        sc(a,b,c);
        unsigned int ans=0;
        for(int i=1;i<=a;i++)
            ans=(ans+phmu[i]*(a/i*(b/f2[i])*(c/f3[i])));
        printf("%d\n",ans&((1<<30)-1));
    }
    return 0;
}