オイラーの線形関数に画面から、すべての可能性にあなたはそれを理解することができます!

この記事の動機:それを成長させるには何がある場合は?(それについてまず希望的観測)
紙難易度:ユニバーサル- →増加+

\(パート\ ;. 1 \) ふるいリニア

素数をスクリーニングすることができるだけでなく、製品のすべてが機能することができ(\ O(n))は\スクリーンアウト。
\(PS \) のみ乗法関数\(\ FORALL X、P \でY \) ここで、\(P \)は素数の集合である)、\(F(AB&)= F(A)F(B )\)算術関数。
私はあなたの好みのエリクセン画面を閉じていませんが、羅区\(1E8は\)まだあなたのためのカードになります。
しかし、あなたはスキップすることはできません:
エッペンドルフ画面を、完全な名前は明らかに忘れてしまったものです(以下、それ以上)\ qwq(\、コアアイデアがでなければならない合成数を取得するために、現在の数を乗じた既存の素数を使用するのですか?) 。
ふるいの下には、リニア素数であります:

    judge[1]=true;
    for(int i=2;i<=maxn;i++)
    {
        if(i*i>maxn) continue;
        if(!judge[i])
        {
            for(int j=2*i;j<=maxn;j+=i) judge[j]=true;//是合数
        }
    }

一つは、それを理解することができます。
複雑性分析(しません):
我々は、素数密度知る\(\ dfrac {n}は{ \ LN、N} \) 次に、係合各数のため、\(X \)スクリーンに(\ \ dfrac {MAXN} { X} \) しかしながら回彼は近い合計である(ログnは\ \)\それがあるべきよう、(難しいが死亡した)された(O(N \)N-をログ\ログ\)\(それが彼の詰まったの運命を変更しない)、定数に類似
オイラーが発見したのです(誰でもできる)、いくつかの数は数回上映されます偉大な神、どのような彼はできません\(O(n)と\)のような原因、\(6 \) です\(3 \)画面は二回、我々は書くことができます。

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

なぜのみ再びスクリーン?
割り切れるならば考えてみて、その後も要因があるかもしれないバック良いに投げ、彼の画面をオフに乗。
複雑さがあるので、\(O(n)と\) その後、カードは動作しません。

\(パート\; 2 \) オイラー機能

オイラーの関数を定義した\(\ PSI(n)を\ ) と\(N \) 互いに素数、泥棒が良い兄を入れて
\(\ PSI(6)\)あなたがたの数?ここで列挙することができ、ある\(O(N \ N-ログ)\) 彼は良い方法を話した:
書き込みすべての分母がある(6 \)は\以下である(1 \)\得点。
\ [\ dfrac {1} { 6}、\ dfrac {2} {6}、\ dfrac {3} {6}、\ dfrac {4} {6}、\ dfrac {5} {6}、\ dfrac { 6}、{6} \]
パケットを簡略化した後:
\ [\ dfrac {1} {6}、\ dfrac {1} {3}、\ dfrac {1} {2}、\ dfrac {2} {3}、。。。。。 \ dfrac {5} {6}
、\ dfrac {1} {1} \] 次に:
\ [\ PSI = 2、\ PSI = 2、\ PSI(2)= 1、\ PSI((6)(3)。 1)= 1 \]
それは意味:
\ [\ sum_ {D | N-} \ PSI(d)はN- \]を=
私は再びそれを学び、カウンターMoの証明となる機会を持っていた場合、観察された誘導は、タイトではない、明らかです。

\(パート\ ;. 3 \) 線形を探しています

オイラー関数は、それができることを保証するために、乗法関数である(\ O(n))は\選別、原則的には、より複雑で、それが学習しないようにお勧めします\(qwq \) はるかに良い以下を読んで、とにかく、I

\(第\ ;. 4 \) 単機能のオイラー数

イベントを検討してください:
\ [\テキストPにおけるX \ {場合}、\ PSI
(X)= X-1 \] 自体のみプライムしない、我々が呼ぶものの性質。

自然IIは:検討合成数を\(A \)を満足\(A = P ^ K(K> 1、ZにおけるK \)\) 明らかに彼の素数と[P、で\(B \ 2P、 ^ {K ...... P-3P-P-1}] \) ()私は中括弧をプレイしていない、私は休憩を与えます。
次に、\(\ PSI(A)= ^ P ^ {K-KP 1} = K ^ P(1- \ dfrac {} {P} 1)\)

3つのプロパティ:最も一般的な場合は、各コの数\(Aは\)一意分解式を書くことができる:
\ [P_1 = A ^ {^ {P_2 K_2 K_1}} ^ {... P_N K_n} \ ]
即ち:
\ [A = \ prod_ 1 = {I} ^ {^ N-K_I P_I} \]
幸いオイラー関数満たすために、製品の特別な機能である\(\ PSI(NM)= \ PSI(n)を\ PSI(M)\) 当然のドメイン(セットアップ)。
その後、
\ [\ PSI()= \ prod_ {I = 1} ^ N \ PSI(P_I ^ {K_I})= \ prod_ {I = 1} ^ N P_I ^ {K_I} \ prod_ {I = 1} ^ N(1- \ dfrac {1}
{P_I})= A \ prod_ {iは1 =} ^ N(1- \ dfrac {1} {P_I})\] ここで、我々はでき(O(\ SQRTを\ {N})\)オイラー数の導関数。実際には、我々は以前考えていたと素因数を学ぶことは、列挙検証に似ている:
コード:

int phi(int n)
{
    int ans=n;
    for(int i=2;i<=sqrt(n);i++)
    {
        if(n%i==0)
        {
            ans=ans/i*(i-1);//这是一个p,注意先除再乘,防止炸int
            while(n%i==0) n/=i; //把质数次方因子筛没了,就不会错了
        }
    }
    if(n>=2) ans=ans/n*(n-1);//最后有可能剩下
    return ans;
}

しかし、一部の人々は書いていません。

int phi(int n)
{
    int ans=1,now;
    for(int i=1;i<=sqrt(n);i++) 
    {
        now=1;
        if(n%i==0)
        {
            now=i-1,n/=i;
            while(n%i==0) now*=i,n/=i;
        }
        ans*=now;
    }
    if(n!=1) ans*=n-1;
    return ans;

画分(のために簡単に説明すると、下\(P ^ K \) の変形例を考える:
\ [\ PSI(K ^ P)= KP ^ P ^ {} = 1 K-KP 1} ^ {(P-。 1)\]
その後、素数が現れる見つけた(p \)\最初による1 \) - \(Pもう一度、(K-1 \)\時間\(P \) :、他は同じですが、ここでは

now=i-1,n/=i;

それに加えて、その注意\(今、ANS \)を記録して、混乱することはできません。

\(その\ 5 \)リターン。\(その\ 3 \)

言いたい残り。

phi[1]=1;
    for(int i=2;i<=n;i++)
    {
        if(!vis[i]) p[++cnt]=i,phi[i]=i-1;//质数只有自身与自己不互质 
        for(int j=1;p[j]&&i*p[j]<=n;j++)
        {
            vis[i*p[j]]=1;
            if(!(i%p[j]))
            {
                phi[i*p[j]]=phi[i]*p[j];
                //这里是平方因子了,不要减1 
                break;
            }
            else phi[i*p[j]]=phi[i]*(p[j]-1);//第一次出现因子,乘p-1 
        }
    }

本質的にはコード。
実際には、画面と素数は同じです。
リニアふるいが、非常に\(NB \)ので、すべての乗法機能それは(ないの一見大きな驚異の複雑さをカバーするために)彼を恐れています。

\(パート\; 6 \)オイラーの定理

予備知識:高速電力。
おそらく書かれた、複雑である(O(\ nはログ)\ \)があります。

ll quickpow(ll a,ll b)
{
    ll ans=1,base=a;
    while(b!=0)
    {
        if(b&1!=0)//b%2==1;
        {
            ans*=base;
        }
        base*=base;
        b>>=1;//b/=2;
    }
    return ans;
}

あなたも、より高速に実行するために、乗算の独自の権限を定義することができます。
しかし、どのように大きなインデックスにそれを行うには?
でも\(O(\ログN) \) ああ行くだろう!
オイラーは偉大な定理を作った、我々はとして知られ、彼を覚えているオイラーの定理

もし\(\ GCD(A、M)= 1 \。) 次いで:
\ [^ {A \ PSI(M)} \ equiv1 \ PMOD {M} \]
彼は、提案されていないと考えているオイラーの定理の拡張を
\ [^ B \当量\開始{ケース} ^ B&B <\ PSI(M)\\ ^ {B \; MOD \; \ PSI(M)+ \ PSI(M)}&B \ geqslant \ PSI( M)\端{ケース} \
] このように、第1の予備処理(\ \ PSI(m)は\)次に文字列であるリードに死にます。
複雑多分それは、\(O(Len_B + \ SQRT {M} + \ログM)\) すべての後に、\(\ PSI(M)\ ) の上限である\(M \)この質問によって、)。
コード:

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int phi(int x)//欧拉函数
{
    int ans=1,num=1;
    for(int i=2;i*i<=x;i++)
    {
        if(!(x%i))
        {
            num=i-1,x/=i;
            while(!(x%i)) num=num*i,x/=i;
            ans=num*ans;
        }
    }
    if(x!=1) ans=ans*(x-1);
    return ans;
}
inline int read(int mod)//改进快读,让他边读边输入
{
    //g用来判断b与phi(m)的大小,如果小于,就不能加了,这是坑点!
    int x=0;
    bool g=false;
    char c=getchar();
    while(c<'0'||c>'9') c=getchar();
    while(c>='0'&&c<='9')
    {
        x=(x<<3)+(x<<1)+(c^'0');
        if(x>=mod) x%=mod,g=true;
        c=getchar();
    }
    if(g) return (x+mod);
    else return x;
}
int a,mod;
char b[20000005];
inline int quickpow(int a,int b)//快速幂
{
    long long ans=1,base=(long long)a;
    while(b)
    {
        if(b&1) ans=ans*base%mod;
        b>>=1;
        base=base*base%mod;
    }
    return (int)(ans%mod);
}
int p;
int main()
{
    scanf("%d%d",&a,&mod);
    int p=phi(mod);
    int cishu=read(p);//得出的化简次数
    int s=quickpow(a,cishu);
    printf("%d\n",s);
    return 0;
}

おそらく、これらの友人の後、だけでなく、物事のいくつかにもより深いポイント。

おすすめ

転載: www.cnblogs.com/tlx-blog/p/12369301.html