1.基本的な概念と共通のコード
(1)素数(质数)
int prime[maxn],tot=0;
bool vis[maxn];
void init(int n)
{
vis[1]=1;
for(int i=2;i<=n;++i)
{
if(!vis[i]) prime[++tot]=i;
for(int j=1;j<=tot&&prime[j]*i<=n;++j)
{
vis[i*prime[j]]=1;
if(i%prime[j]==0) break;//每个数都只会被它最小的素数因子筛掉
}
}
}//线性筛素数
(2)ユークリッドアルゴリズム(ユークリッド)
#define ll long long
ll gcd(ll a,ll b)
{
return b==0?a:gcd(b,a%b);
}
拡張ユークリッドアルゴリズム
int exgcd(int a,int b,int &d,int &x,int &y)
{
if(!b)
{
x=1,y=0;
return d=a;
}
else
{
exgcd(b,a%b,d,y,x);
y-=x*(a/b);
}
}//可用于求ax+by=d的一组解,当且仅当d=gcd(a,b)时有解(若要通过此特解推出其他解,每次x减小b/d,y增加a/d即可)
ユークリッドは元を反転することができる拡張(逆おそらく金型内のカウントダウンを意味するものと理解されます)
第一金型Bの意味の下、金型Bの意味での逆元を必要に応じて(B)= 1、すなわち、AおよびBは、我々が互いに素と仮定さGCD但し逆元を有する金型B意義で逆のx、1合同型Bで、その後斧である、あなたは= 1で斧+を取得することができます(+ 1で=斧である必要があり、転置は斧バイ= 1になった後、私たちは= Bを聞かせて-b = 1によって斧+)
(3)急速電源
#define LL long long
LL pow_mod(LL a,LL b,int mod)
{
LL ans=1;
while(b)
{
if(b&1)
{
ans=(ans*a)%mod;
}
a=(a*a)%mod;
b>>=1;
}
}
(4)オイラー関数(自分の素数でカウント数以上ではありません)
\ [\ varphi(N)= N(FRAC \ 1- {1} {P_1})(1- \ FRAC {1} {P_2})\ cdots(FRAC \ 1- {1} {p_k})\]
証明:
正の整数nは、固有分解を与えられ
\ [N = P_1 ^ {A_1
} P_2 ^ {A_2} P_3 ^ {A_3} \ cdots p_k ^ {a_k} \] 包含と排除して、第1の全Nから減算され、P1をP2、P3 ... PK(PI素数であり、それは倍数でない者は、そのプライム)の、すなわち、NN / P1-N / P2 ...-の数倍 N / PK( PI最大提供Nは、PI * tの複数を満たすために以下であるN / PIように、Tが決定される)、次いで追加「はまた、2の倍数の数であり、数の倍数を減算する数ながら3であります.. 。、それは、結果として得られる式である:
[\ varphi(N)= \ sum_ {S \ subseteq P_1、P_2、... P_K} \( - 1)^ {| S |} \ {N-FRAC} {\ prod_ {P_Iの\イプシロンS}} P_I \]
int phi[maxn];
void init(int n)
{
phi[1]=1;
for(int i=2;i<=n;++i)
{
phi[i]=i;
}
for(int i=2;i<=n;++i)
{
if(phi[i]==i)
{
for(int j=i;j<=n;j+=i)
{
phi[j]=phi[j]/i*(i-1);
}
}
}
}//筛表法求欧拉函数
(5)残りの行を、逆モジュロ乗算
ライン剰余モジュロnは残りの行を簡単にするために、完全{0,1,2、...、N-1}であることが人気のある(また、縮小系と呼ぶ)完全nが残数の素数であるシステム。
完全に記述された係数を、残りの最も一般的なシステムN Z / NZである、のように書くことができる:
\ [Z / nまたはZ_N \]
、収縮系と呼ぶ
\ [Z_N ^ * \]
#define LL long long
LL inv(LL a,LL mod)
{
LL d,x,y;
return exgcd(a,mod,d,x,y)==1?(x+mod)%mod:-1;
}//模乘法的逆
もう一つの方法は、逆オイラーの定理を使用することです
任意収縮線に対して、任意の整数n> 1の所定のN元素で、
\ [A ^ {\ varphi(N)} \ equiv1(MOD \クワッドN)\]
このように逆要素である
\ [ ^ {\ varphi(N)
-1} MOD \クワッドN \] nが素数である場合、
\ [\ varphi(N)=
N-1 \] したがって、逆pow_mod(N-2であり、 nは)
2.モード方程式
(1)線形モデル式
\ [AX \当量のB(MOD \クワッドN)\]
、AX-NY = Bに約D = GCD(N)の数が'B、又は両側Dで除算しながら、a'x-n'y = B与えるようにされていない解決策を入れていない ='を/ D、N '= N / D、B' = B / D、 すなわち
\ [a'xの\当量のB '(
MOD \クワッドN')\] このとき、A '及びn'は互いに素を有しているので、 '鋳型N'意味で逆元によって残され、溶液は次に:
\ [X \当量(A ')^ { - 1} B'(MOD \クワッドN ')\]
この解決策は、弾性率であり、n'はシステムの残りの要素は、我々は、nエレメント線として表される残りのモジュロを入れなければなりません。オーダー(A ')^ - 1件のB' = P、上記の溶液に対応するx = P、X = P + n 'は、XのP + 2N ='、XのP + 3N「=、.... 金型のためのN、Pの中の+ 'およびp + JN'合同場合、(のP + ') - ( P + JN')=(IJ)N ' nの倍数であり、したがって、と、(のIJ)A D倍数(GCD(N))。換言すれば、残りの行は、Nを法、
\ [AXの\当量のB(MOD \クワッドN)\]
正確Pの溶液に、p + n 'は、P dは + 2N'、P + 3Nを」、。 ..、P +(D-1 )N」。
あなたは私たちがそれを行うべきか、複数の式、変数、または一つだけを持っている場合は?
その後、次の定理を使います
(2)中国の剰余定理(中国の剰余定理)
方程式を考える
\ [X \当量a_iを(MOD
\クワッドM_I)\] と全ペアワイズ互いに素MI。Mは、MIの全ての製品のWi = M / MI、GCD(WI、MI)= 1とします 。
PIとのユークリッドアルゴリズムを拡張し、気は、ウィスコンシン*のPI +のMI *チー=ことが分かる 1。その後、許可EI =ウィスコンシン* PIを、単一の式に相当する式
\ [X \当量e_1a_1 + e_2a_2 + \ cdots + e_na_n(MOD \クワッドM)\]
ユニーク有する、即ちモジュロMの行を残り、一次方程式ソリューション。
証明:式のWi PI MI +型の両側チー= 1マイル直ちに得ることができる
\ [e_i \当量1(MOD \クワッドM_I)\]
J iに等しくないすべてのために、ウィスコンシンMJは、の倍数であるのに対し、したがって
\ [e_i \当量0(MOD \クワッドM_j)\]
、残りは1以外のモジュロ加算eiaiのX0 MIが* = AIが愛場合、ように、残りの残りの項はゼロです。
#define LL long long
LL crt(int n,int* a,int* m)
{
LL M=1,d,x,y,x=0;
for(int i=1;i<=n;++i) M*=m[i];
for(int i=1;i<=n;++i)
{
LL w=M/m[i];
exgcd(m[i],w,d,d,y);
x=(x+y*w*a[i])%M;
}
return (x+M)%M;
}
(3)離散対数
簡単にするために、我々は、最も簡単な場合を考えるすなわち、Nが素数モジュラス式である場合
\ [A ^ X \ B当量
(MOD \クワッドn)を\] nがあれば、0ではないように、素数であるので、逆A ^ -1が存在しなければなりません。オイラーの定理は、単にチェックすることにより、X = 0,1,2、...、N- 1は、 解決策にはありません。以降
\ [A ^ {N-1} \当量1(MOD \ N-クワッド)\]
、N-1 Xは^ Xサイクルの開始時に超えます。
我々は、フロントMをチェックすなわちアイテム、^ 0、A ^ 1、...、^値モジュロN(M-1)Bである場合、及び(Mは、我々は、N ^(1/2)を作るです) ^ imodn EIに格納され、逆A ^ m個のA ^を算出する( - m)を。
、^ Mを考えるA ^(M + 1)、...、A ^(2M-1)。それらの一つは、私は存在に対応するソリューションがある場合ので11は、チェックしない
\ [e_i * A ^ m個の\当量のB(MOD \ N-クワッド)を\]
与える- (M)^によって両側で、
\ [e_iの\当量のB '(MOD
\クワッドN)\] 前記
\ [B' = A ^ {
- M} B(MOD \クワッドN)\]は、 したがって、単にそのようなEiがにB」に等しいかどうかをテスト。
( - 2メートル)* B ^()mod nをされていない場合、その後、B '' =よう^ 2メートル、^(2M + 1)、...、^(3M-1)を考えます
したがって、我々は^(M *はM-1)に記載の方法を列挙しなければなりません
int pow_mod(int a,int b,int mod)
{
int ans=1;
while(b)
{
if(b&1) ans=(ans*a)%mod;
a=(a*a)%mod;
b>>=1;
}
return ans;
}
int log_mod(int a,int b,int n)
{
int m,v,e=1;
m=(int)sqrt(n+0.5);
v=pow_mod(pow_mod(a,m,n),n-2,n);
map<int,int> x;
x[1]=0;
for(int i=1;i<m;++i)
{
e=(e*a)%n;
if(!x.count(e)) x[e]=i;
}
for(int i=0;i<m;++i)//考虑a^(im),a^(im+1),...,a^(im+m-1)
{
if(x.count(b)) return i*m+x[b];
b=(b*v)%n;
}
return -1;
}//这就是可用于解决离散对数的大步小步算法(Baby_Step_Giant_Step Algorithm),复杂
//度O(n^(1/2)logn)