[BZOJ4407]神拡張バージョンへの怒り(メビウス反転)

問題の表面を見るにはここをクリック

一般的な質問の意味:シーク\(\ sum_ 1} ^ {N-I = \ sum_ {J} = ^ MGCD 1(I、J)^ K \。)

序文

\(月\ 28 \)ブラシタイトル計画(3/6)、アルゴリズムタグ:メビウス反転&デュティーチふるいです。

リニアふるいカスタム乗法機能:新しいスキルを学びます。

メビウス反転

まず、列挙するためのルーチンに従い、(GCD \)\取得します:

\ [\ sum_ {D = 1} ^ {分(N、M)} D ^ K \ sum_ {i = 1} ^ {\ lfloor \ FRAC ND \ rfloor} \ sum_ {J = 1} ^ {\ lfloor \ FRAC MD \ rfloor} [GCD(i、j)は== 1] \]

取得するメビウス反転:

\ [\ sum_ {D = 1} ^ {分(N、M)} D ^ K \ sum_ {P = 1} ^ {分(\ lfloor \ FRAC ND \ rfloor、\ lfloor \ FRAC MD \ rfloor)} \ MU(P)\ lfloor \ FRAC N {DP} \ rfloor \ lfloor \ FRAC M {DP} \ rfloor \]

考えてみましょう列挙\(D = DP \) 与えます。

\ [\ sum_ {D = 1} ^ {分(N、M)} \ lfloor \ FRACのnD \ rfloor \ lfloor \ FRAC MD \ rfloor \ sum_ {D | D} D ^ K \ミュー(\ FRAC DD)\ ]

セット\(F(D)= \ sum_ {D | D} D ^ K \ MU(\ FRAC DD)\) 元の式に相当します:

\ [\ sum_ {D = 1} ^ {分(N、M)} \ lfloor \ FRACのnD \ rfloor \ lfloor \ FRAC MD \ rfloor F(D)\]

のみを必要とする\(F(D)を\) ブロックを容易に分割することによって、この問題を解決することができます。

どのように見つけるために:重要な質問だから、\(F(D)\)

リニア乗法関数ふるいです

明らかに\(F(n)は\)乗法関数です。

私たちは聞かせている場合、\(N- = \ prod_ 1 = {I} ^ {^ tP_i a_iを} \。)(\ (P \)素数である)、そして:

\ [fは(N)= \ prod_ {I = 1} ^ TF(P_I ^ {a_iを})\]

簡略化考え\(F(P_I} ^ {a_iを)\)

\ [F(P_I ^ {a_iを})= \ sum_ {D | P_I ^ {a_iを}} D ^ K \ミュー(\ FRAC DD)= 1 ^ K \回\ミュー(P_I ^ {a_iを})+ P_I ^ K \時間\ミュー(P_I ^ {a_iを-1})+ ... + P_I ^ {a_iを\倍のk} \回\ MU(1)\]

\(\ MU \)は、理解定義(\ \ MU(P_I} ^ {a_iを)、\ MU(P_I-a_iを^ {}。1)、...、\ MU(P_I ^ 2))\同じです\(0 \) と言うことですつまり、我々は最後の2つの式を考慮する必要があります。すなわち:

\ [F(P_I ^ {a_iを})= P_I ^ {(a_iを-1)\倍のk} \回\ MU(P_I)+ P_I ^ {a_iを\倍のk} \回\ MU(1)= - P_I ^ {(a_iを-1)\回K} + P_I ^ {a_iを\回K} = P_I ^ {(a_iを-1)\回K}(P_I ^ K-1)\]

つまり、があります。

\ [fは(N)= \ prod_ {I = 1} ^ tP_i ^ {(a_iを-1)\回K}(P_I ^ K-1)\]

そして、よくやりました。

リニア画面は、例えば、我々は、境界状態があり得ることができます。

\ [F(N)= \開始{ケース} 1 - (N = 1)\\ P ^ K-1・(Nは\ \素数である)\端{ケース} \]

ふるい方法がある時に続いてふるいを考慮してください。

\ [F(I \回P_j)= \開始{ケース} F(i)が\回(P_j)&F(P_j \ない{|} I)\\ F(I)\回P_I ^ K&(P_j | I )\端{ケース} \]

これは、前述のリリース自身の式から理解することができます。

コード

#include<bits/stdc++.h>
#define Tp template<typename Ty>
#define Ts template<typename Ty,typename... Ar>
#define Reg register
#define RI Reg int
#define Con const
#define CI Con int&
#define I inline
#define W while
#define N 10000000
#define X 1000000007
using namespace std;
int n,m,k;
I int Qpow(RI x,RI y) {RI t=1;W(y) y&1&&(t=1LL*t*x%X),x=1LL*x*x%X,y>>=1;return t;}
template<int SZ> class LinearSieve//线性筛
{
    private:
        int Pt,P[SZ+5],f[SZ+5],p[SZ+5];
    public:
        I int operator [] (CI x) Con {return f[x];}
        I void Init()
        {
            RI i,j;for(f[1]=1,i=2;i<=SZ;++i)
            {
                !P[i]&&(P[++Pt]=i,p[i]=Qpow(i,k),f[i]=p[i]-1);
                for(j=1;j<=Pt&&i*P[j]<=SZ;++j)
                    if(P[i*P[j]]=1,i%P[j]) f[i*P[j]]=1LL*f[i]*f[P[j]]%X;
                    else {f[i*P[j]]=1LL*f[i]*p[P[j]]%X;break;}
            }
            for(i=2;i<=SZ;++i) f[i]=(f[i]+f[i-1])%X;
        }
};LinearSieve<N> F;
int main()
{
    RI Tt,i,j,l,r,t;scanf("%d%d",&Tt,&k),F.Init();W(Tt--)
    {
        for(scanf("%d%d",&n,&m),t=0,l=1;l<=min(n,m);l=r+1)//除法分块
            r=min(n/(n/l),m/(m/l)),t=(1LL*(n/l)*(m/l)%X*(F[r]-F[l-1]+X)+t)%X;
        printf("%d\n",t);
    }return 0;
}

おすすめ

転載: www.cnblogs.com/chenxiaoran666/p/BZOJ4407.html