ドゥは、ふるい学習の概要を教えて

ドゥは、ふるい学習の概要を教えて

序文

ドゥは、ふるいは非常にNB聞いてきた教えが、それについて学ぶことはとてもピットを埋めるために持っていた、鳩となって= =が、最近辛いあまりにも多くの数学の問題が発生しました。

推奨するブログ:
ポータル1
ポータル2
ポータル3

:また杜は、ふるいはメビウス関数にいくつかの事前の知識、事前の書面記事、だけの方法、それはTieshanglaiかかる場合が教えるポータル

テキスト

算術関数:我々は通常のようないくつかの特別な機能に遭遇\(\ varphi、\ミュー\ ) 算術関数に属しています。

乗法関数
定義:数論的関数の既知の関数場合、および(。。F(1)= \ 1)\、任意の2つの互いに素のための満足\(P、Q \)がある:\(Fは( P \ CDOT Q)= F(P)\ CDOT F(Q)は\) 次いで呼ばれる\(F \)は乗法関数です。任意の二つの数字のためならば、特別に、\(P-、Qの\) そこ\(F(P-\ CDOT Q)F(P-)\ CDOT F(q)を\ =) それが呼び出されるような関数として完全乗法機能。

共通乗法機能:

  • \(\ MU(N-)\) -非常に一般的であるメビウス関数、それは自然の一部の理解を持っている必要があります。
  • \(\ varphi(N-)\) -オイラー関数は、として定義されている\(1 \) (\ \ N-)を有する(N- \)\素数の数。
  • \(D(N)\) -数の除数数は、約からの数を表します。

  • (乗法機能を完了します):
  • \(\ varepsilon(N-)\) -メンバシップ関数、(\ N = 1)\、その値が0の残り時間の値が1である場合、
  • \(I(N)\) -恒等関数に関係なくの\(\ N-)どの1に等しい定数値の値。
  • \(ID(N)\) -機能ユニット、\(ID(N)= N- \)

これらの一見完全に乗法関数は、実際には、使用をたくさん持っている、比較的簡単です。彼らは完全に乗法の性質がよく証明されています。

ディリクレ畳み込み:
定義:二つの機能\(F(N)、G (n)は\) ディリクレ畳み込みと呼ばれる((F * G)(N-)\)\、式は以下と等価です\(\ sum_ {D |} N-F(D)G(\ {N-FRAC} {D})\)括弧の前にオブジェクトの畳み込みを示し、括弧内の後者は、畳み込みの範囲を示します。
自然
ディリクレ畳み込み演算は、いくつかの非常に有用な性質を持っています:

  • 為替レート:\(F * F * G = G \)
  • 連想:\((F * G)= F * H *(G * H)\)
  • 分配法則:\(F *(G + H)+ = F * F * G H \)

より重要な性質もあります:
場合は\(F、Gの\は)それから、乗法関数である\(のF * gは\)にも乗法関数です。
ドゥは、関数の畳み込み積によって判断し、ふるいを教える、それは非常に一般的な技術です。
上記の我々のメンバーシップ関数の言及に加えて\(\ varepsilonの\)を、ある(\ varepsilon F = F * \)\、即ち、単位乗算機能の要素1のように作用します。

アプリケーション:

  • メビウス関数のための\(\ MU \)がある\(\ * I MU = \ varepsilonの\)
  • オイラー関数のための\(\ varphi \) そこ\(\ Iは、上記= \ ID言及* varphi)を

以上の2つの式は、これら二つの性質の最も一般的に使用される機能の一つです。:によって彼らはまた何かを証明するために使用することができます
例えば、メビウス反転の形のために、それが知られている\(* I \ F = F)を、我々は同時に両側にロールバックされます、\(\ MU \) そうとそうそれは型である\(MU = * F * F. \のvarepsilon = F \) すなわち\(F * = F. \ MU \)
それのいくつかを証明するために簡単に多くのことを感じていないですか?
そこについて\(\ varphi I = ID * \) ロールの両側にしながら、\(\ MU \) そこされる\(\ varphi = ID * \ MU = \ sum_ {D | N}のD \ミュー(\ {} {D N-FRAC})\)この式にも便利です。
要するに、マスター\(\ムー、\ varphi \ ) 自然とディリクレ畳み込みは非常に良いです。

ドゥは、ふるいを教えます

ドゥは、ふるいの友人を教える-フロントでは、その後、我々は質問に来る、いくつかの事前の知識です。
duがふるい教示に主に圧力用いられる線形時間\(O(N ^ {\ FRAC {2} {3}})\) 乗法関数プレフィックスで得られます。私は非常に強力な感じではないでしょうか?まあ、実際には、デュ画面を教えることは知って見下ろすので、魔法ではありません〜

今乗法関数のための\(F \) 必要\(\ sum_ = {I}。1 ^ NF(I)\)と呼ばれる、\(S(N)が\)
構成\(F * G = Hで\) そこである:
\ [\整列} {\ sum_ {I}を始める1 ^ = NH(I)=&\ sum_ {I} 1 = G ^ * NF =&\\。 \ sum_ {i = 1} ^ n個の\ sum_ {D | I} F(\ FRAC {I} {D})G(D)\\ =&\ sum_dg(D)\ sum_ {D | I} F(\ FRAC {I} {D})
\\ =&\ sum_dg(D)S(\ lfloorの\のFRAC {n}が{D} \ rfloor)\\ \端{整列} \] 今最初の選抜、そこである
(1)\ [\ sum_ {I} 1 ^ = NH(I)G = \ CDOT S(N)+ \ sum_ {D} ^ 2 = NG(D)S(\ lfloor \ {N-FRAC } {D}は\ rfloor)\
] :式は、と等価である
。\ sum_ {D - [G(1)CDOT S \ \(N)= \ sum_ 1} ^ {N-I =(F * G)(I) = 2} ^ NG(D) S(\ lfloorの\のFRAC {n}が{D} \ rfloor)\]

我々は乗法関数見つけることができるかどうか\(G \)を、そう\(\ sum_ {i = 1 } ^ N(のF *のG)は、(i)\) この部分の接頭語と直接リア分割しながら迅速にシークすることができますブロックは、それが加速する中で役割を果たすことができます。

それを説明するために、いくつかの一般的な例:

  • \(\ sum_ {i = 1} ^ n個の\ミュー(I)\)

私たちは知っている:\(\ * MU I = \ varepsilonの\) および\(\ varepsilonの\は)この関数は十分に簡単です!それはすぐに加算されるので、我々は作る\(G = \ varepsilon \) 次いで式に加算することができる:
\ [S(N)= 1- \ sum_ {D} = 2 ^ナノ秒(\ lfloorを\ FRAC {n}は{D}
\ rfloor)\] 後部に、ブロック処理を分割してもよいです。

  • \(\ sum_ {i = 1} ^ n個の\ varphi(I)\)

またはの使用\(\ varphi \)文字は、ときにそのボリューム我々は知っている\(私は\) :、比較的単純な関数になることが可能である\(上記のid \を述べました)この合計は、高速をサポートすることで、我々がアクセスダイレクト(G = Iが\)\をすることができます。

  • \(\ sum_ {i = 1 ^ NI} \ varphi(I)\)

これはあまりよくない取引のように見える、我々は持っていると仮定し\(G \)を、我々はコンボリューションの形で表現されます\(\ sum_ {D | N-}(D用の\ varphi(D))G(\ FRAC N-D} {} {)\)
この式、観察\(G = IDの\)は、複数の\(D \)をなくすことができ、残りの\(n-は\)外部挙げることができます。
そう自然に取ると思う(G = IDの\)\それは、次に\(| = Iが\ N- \ varphi(D)(F * G)(I)= Iはsum_ {D}を\します)
式は非常に簡単になり、非常に素晴らしい感じていません。

  • \(\ sum_ {i = 1} ^ NI ^ 2 \ varphi(I)\)

上記の考え方と同様に、第1の畳み込み演算フォームに書き込みがある:\(\ sum_ {D | D ^ N-2} \ varphi(D)G(\ {N-FRAC} {D})\)
同様に、行うことが考えられる\(G = IDを\)がある:\(。\ sum_ {I = NF * G. 1} ^ = \ sum_ = {I} 1 ^のNi ^ 2 \) 実際に上記と同じです日常〜

とにかく探し\(グラム\)このステップでは、特定の観察と忍耐を必要とし、それはライン上でのテストではありません。

特定の実装は、再帰的に実施することができる場合には、\(GetSumは(N)\)を得ることができる\(Sは(N)\) 処理は再帰的であってもよいです。
それは直接DUは、ふるいを教え、あなたがメインの定理カードを使用することができる証明した後、複雑です\(O(N ^ {\ FRAC {3} {4}})\) 、私たちが最初にすることができますプリアウト\(N ^ {\ FRAC {2} {3 }} \) プレフィックスと、複雑であるように、\は(O(N ^ {\ FRAC {2} {3}})\) 。
操作のメモリを追加することができ、それが特にあるデータの複数のセットのために、速くなることがあります。
:タイトルテンプレートのコードの下に添付
羅区P4213

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 5e6 + 5;
int mu[N], p[N];
ll phi[N];
bool chk[N];
unordered_map <int, ll> mp1, mp2;
void init() {
    mu[1] = phi[1] = 1;
    int cnt = 0, k = N - 1;
    for(int i = 2; i <= k; i++) {
        if(!chk[i]) p[++cnt] = i, mu[i] = -1, phi[i] = i - 1;
        for(int j = 1; j <= cnt && i * p[j] <= k; j++) {
            chk[i * p[j]] = 1;
            if(i % p[j] == 0) {mu[i * p[j]] = 0; phi[i * p[j]] = phi[i] * p[j]; break;}
            mu[i * p[j]] = -mu[i]; phi[i * p[j]] = phi[i] * (p[j] - 1);
        }
    }
    for(int i = 1; i < N; i++) mu[i] += mu[i - 1], phi[i] += phi[i - 1];
}
ll djs_mu(int n) {
    if(n <= 5000000) return mu[n];
    if(mp1[n]) return mp1[n];
    ll ans = 1;
    for(int i = 2, j; i <= n; i = j + 1) {
        j = n / (n / i);
        ans -= (j - i + 1) * djs_mu(n / i);
    }
    return mp1[n] = ans;
}
ll djs_phi(int n) {
    if(n <= 5000000) return phi[n];
    if(mp2[n]) return mp2[n];
    ll ans = 1ll * (n + 1) * n / 2;
    for(int i = 2, j; i <= n; i = j + 1) {
        j = n / (n / i);
        ans -= (j - i + 1) * djs_phi(n / i);
    }
    return mp2[n] = ans;
}
int n, T;
int main() {
    init();
    cin >> T;
    while(T--) {
        cin >> n;
        ll ans1 = djs_mu(n);
        ll ans2 = djs_phi(n);
        cout << ans2 << ' ' << ans1 << '\n';
    }
    return 0;
}

おすすめ

転載: www.cnblogs.com/heyuhhh/p/11409516.html