この記事の動機:それを成長させるには何がある場合は?(それについてまず希望的観測)
紙難易度:ユニバーサル- →増加+
\(パート\ ;. 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;
}
おそらく、これらの友人の後、だけでなく、物事のいくつかにもより深いポイント。