尤拉定理+費馬小定理
一、尤拉定理
互質關係
如果兩個整數(或者兩個以上的整數)的最大公約數是1,則稱他們為互質。也就是說兩個整數,除了1以外,沒有其它的最大公約數了,這兩個整數就叫做互質關係。
比如說7,11他們的最大公約數只有1,所以他們互質;8,10他們的最大公約數為1,2,所以這兩數不是互質關係。
尤拉函式
尤拉函式φ(n)是小於或等於n的正整數中與n互質的數的數目,稱為尤拉函式
比如說當n=8時,與8能形成互質關係的數有4個,分別是1,3,5,7,所以φ(8)=4
具體φ(n)函式的計算公式,可以分為以下四種情況:
情況一: 當n=1,φ(1)=1
因為1與任何整數都是互質關係,所以當n=1時,φ(1)=1
情況二:當n為質數,φ(n)=n-1
因為質數與小於它的每一個數,都構成互質關係,所以當n為質數時,φ(n)=n-1 。
比如說n=3時,1,2都跟他是互質關係, n=7時,1,2,3,4,5,6都跟他是互質關係。
情況三:n = p^k (p為質數,k為指數,且大於等於1),n是質數的k次方,則φ(p^k) = p^k - p^(k-1) = p^k(1 - 1/p)
比如:φ(8) = φ(2^3) = 2^3 - 2^2 = 4
φ(27) = φ(3^3) = 3^3(1 - 1/3) = 18
情況四: n是兩個互質的整數之積,如:n = p1 * p1,則 φ(n) = φ(p1p2) = φ(p1)φ(p2)
比如:φ(56)=φ(8×7)=φ(8)×φ(7)=4×6=24
同餘定理
給定一個正整數n,如果兩個整數a和b滿足a-b能夠被n整除,即(a-b)/n得到一個整數,那麼就稱整數a與b對模n同餘,記作a≡b(mod n)。這就是同餘定理。
例如:26≡2(mod 12), 26%12 餘2, 2%12餘2, 26-2/12 = 0,所以26與2對模12同餘
尤拉定理
連結: https://www.jianshu.com/p/9007f61e27a8
來源:簡書
二、費馬小定理
費馬小定理是數論中的一個定理:假如a是一個整數,p是一個質數,那麼
如果a不是p的倍數,這個定理也可以寫成(同餘式寫法)
同餘式
如果兩個正整數 a和 b之差能被 n整除,那麼我們就說 a和 b對模n同餘,記作:
證明
任意取一個質數,比如13。考慮從1到12的一系列整數1,2,3,4,5,6,7,8,9,10,11,12,給這些數都乘上一個與13互質的數,比如3,得3,6,9,12,15,18,21,24,27,30,33,36。對於模13來說,這些數同餘於3,6,9,12,2,5,8,11,1,4,7,10。這些餘數實際上就是原來的1,2,3,4,5,6,7,8,9,10,11,12,只是順序不同而已。
把1,2,3,…,12統統乘起來,乘積就是12的階乘12!。把3,6,9,…,36也統統乘起來,並且提出公因子3,乘積就是312×12!。對於模13來說,這兩個乘積都同餘於1,2,3,…,12系列,儘管順序不是一一對應,即312×12!≡12!mod 13。兩邊同時除以12!得312≡1 mod 13。如果用p代替13,用x代替3,就得到費馬小定理xp-1≡1 mod p。
應用
- 計算2^100除以13的餘數
- 證明對於任意整數a而言
恆為2730的倍數。13減1為12,12的正因數有1, 2, 3, 4, 6, 12,分別加1,為2, 3, 4, 5, 7, 13,其中2, 3, 5, 7, 13為質數,
根據定理,
為2的倍數、為3的倍數、為5的倍數、為7的倍數、為13的倍數,即235713=2730的倍數。
連結: https://www.jianshu.com/p/e3df7e5d9c38
來源:簡書
給定a,n求出 S=((((aa)a)a)a⋅⋅⋅⋅)a (mod 998244353)共n個a。
輸入:
輸入僅一行. 兩個正整數a和n
輸出:
輸出僅一行. 一個正整數
樣例解釋:
((22)2)2mod 998244353 = 256
資料範圍
a,n <= 1018
思路:
先求出指數,即 an-1(快速冪求解),並將指數對mod-1(因為mod是質數,那麼φ(mod)= mod-1),再用更新後的指數做為新的指數用快速冪求解即可。
程式碼如下:
#include<cstdio>
typedef long long ll;
ll a,n;
const int M=998244353; ll mi(ll a,ll b,int mod) { ll re=1; a%=mod; while (b) { if (b&1) re=(re*a)%mod; a=(a*a)%mod; b>>=1; } return re; } int main() { scanf ("%lld%lld",&a,&n); ll t=mi(a,n-1,M-1); printf("%lld",mi(a,t,M)); return 0; }
課後例題://poj 3696
L,L <= 2*109. 問多少個8連在一起的數是L的倍數。如果不存在就輸出0.
//這裡省略輸入輸出規則,請讀者自行注意
思路:
x個8連在一起可以寫成8*(10x-1)*9,假設d=gcd(L,8)。那麼題目可以表達為:L | 8*(10x-1)*9 , 接下來我們做一些簡單的式子變形:
L | 8*(10x-1)/9 ←→ L*9 | 8*(10x-1) ←→ 9L/d | (10x-1) ←→ 10x ≡ 1 (mod 9L/d)
引理:對於任意互質的正整數a,n,滿足:ax≡1(mod n)最小的整數值 X0 是φ(n)的約數。
證明如下:
(反證法)假設X0不是φ(n)的約數,則φ(n)可以表示為:qX0 + r(0 <= r < X0)。題設有:aX0≡1(mod n),那麼,aqX0≡1(mod n)且正整數a,n互質,所以有尤拉定理:
aφ(n)≡1(mod n),即aqX0 * ar≡1(mod n),繼而得出:ar≡1(mod n),此時r<X0,這與X0是最小的整數值矛盾,所以假設不成立。得證。
φ(9L/d)並將其約數帶入10x ≡ 1 (mod 9L/d)驗證是否成立即可。求尤拉函式和快速冪,時間複雜度為:O(√(n) * log2 n)。程式碼如下:
#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long ll; ll n,mod; int Case; ll gcd(ll a,ll b) { return a%b==0 ? b : gcd(b,a%b); } ll Er(ll x) { ll re=x; for (ll i=2;i*i<=x;i++) { if (x%i==0) { re=re/i*(i-1); while (x%i==0) x/=i; } } if (x>1) re=re/x*(x-1); return re; } ll mul(ll a,ll b,ll p) { ll re=0; while (b) { if (b&1) re=(re+a)%p; a=2*a%p; b>>=1; } return re; } ll ksm(ll a,ll b,ll p) { ll re=1; a%=p; while (b) { if (b&1) re=mul(re,a,p); a=mul(a,a,p); b>>=1; } return re; } int main() { while (scanf ("%lld",&n)) { if (n==0) return 0; Case++; ll d=gcd(n,8); ll phi=Er(9*n/d); mod=9*n/d; ll flag=9223372036854775806; for (ll i=1;i*i<=phi;i++) { if (phi%i==0) { if (ksm(10,i,mod)==1) flag=min(flag,i); if (ksm(10,phi/i,mod)==1) flag=min(flag,phi/i); } } flag==9223372036854775806?printf("Case %d: 0\n",Case):printf("Case %d: %lld\n",Case,flag); } }