数论入门(python)
一、快速冪
例題:杭電oj2035
求A^B的最后三位數表示的整數。說明:A^B的含義是“A的B次方”
由于當b很大時,時間復雜度高,所以要快速冪
*關于取模運算的性質:
(a + b) % p = (a % p + b % p) % p (1)(a - b) % p = (a % p - b % p ) % p (2)(a * b) % p = (a % p * b % p) % p (3)快速冪算法的核心思想就是每一步都把指數分成兩半,而相應的底數做平方運算。這樣不僅能把非常大的指數給不斷變小,所需要執行的循環次數也變小,而最后表示的結果卻一直不會變。
? 不是解答,是我自己隨便寫的板子a,b=31,100000 mid=1 #用來接收盛放奇數冪的底數 mod=10*8+9 while b>0:if b%2: #奇數的處理b=b-1mid=mid*ab=b/2a=a**2%modelse:b = b / 2 #冪減少一半,底數翻倍a = a ** 2 % mod print(mid*a%mod)?二、線性篩
原理并不復雜,但需要看下最后一句
n = int(input()) st = [True]*(n+1) cnt = 0 primes = [] for i in range(2, n+1):if st[i]:cnt += 1primes.append(i)for p in primes:if i*p>n:break #防止越界st[p*i] = Falseif i % p == 0:break #這樣就保證了每個合數被自己的最小質因數所篩,不重復,減少時間復雜度解釋下最后一句:舉個例子 :i = 8 p=2,如果不跳出循環,那么再次循環時,p=3,所得的8 * 3 ?= 2 * 12,在i = 12時會計算再計算一遍24
三、逆元
逆元概念:在mod某個數意義下的倒數。例如5x≡1(mod3),x=2是滿足10=1(mod3),所以稱2是5在mod3意義下的逆元。記為inv(a,p)
需要注意只有a和p互質,a才有關于p的逆元
四大求逆元的方法
·費馬小定理
定理概念:在p是素數的前提下滿足:
稍作變形,有:
即a的p-2次方,便是我們所求。
a,p=3,5 #求a mod p 的逆元,也就是求a的p-2次方 mid=1 p=p-2 while p:if p%2:p=p-1mid=mid*ap=p/2a=a**2continueelse:p = p / 2a = a ** 2 print(mid*a) q=3*2187 print(q%5)輸出: 2187 1·歐拉定理
對于素數p,有:
其中,指數是p的歐拉函數值,也就是小于p的與p互質的數(只有1這一個約數)
類似的變換有:
對于歐拉函數:
其中pi是n的所有質因數:
例如:φ ( 10 ) 的質因數為2,5,所以φ ( 10 ) = 10 * (1 - 1/2) * (1 - 1/5) = 4(1,3,5,7這四個數)
φ (24)的質因數為2,3,所以φ (24)=24* (1 - 1/2) * (1 - 1/3)=8(1,5,7,11,13,17,19,23這八個數)
歐拉函數性質:
1,若n為質數,則φ ( n ) = n - 1;
2,若m與n互質,則φ ( n*m ) = φ ( n ) * φ ( m );
3,若正整數n與a互質,那么就有:
4,若n為奇數時,φ ( 2n ) = φ ( n );
5,若n = pk且p是質數,那么φ ( n ) = (p - 1) * pk-1 = pk - pk-1.
代碼基于快速冪,不再寫了
線性遞推求逆元
略
擴展歐幾里得求逆元
如果gcd(a,p)=1;
那么就有ax+py=1
雙方同時modp
就有ax≡1(modp)
因為py是p的倍數全部約掉了
此時x就是a的逆元
所以只需解出該情況下的擴展歐幾里得方程的解問題就解決了
后續更新:
擴展歐幾里得求ax+by=gcd(a,b)*k
以及通解
四、擴展中國剩余
用于求解模運算方程組,eg:
x=a1?x1+b1(1) x=a2?x2+b2(2) x=a2?x2+b2(3)對于一式和二式,消x得:
a1*x1+a2*x2=b1-b2(因為x是未知量,符號不考慮)利用擴展歐幾里得求x1,得到 :
k=a1*x1+b1
于是我們得到新式子:
x≡k(mod? lcm(a1,a2))
等價于:x=lcm(a1,a2)*x' +k? (4)
同理聯立(3) 和 (4)就能得到解
def ext_gcd(a,b):if not b:x,y=1,0return x,y,ax,y,gcd=ext_gcd(b,a%b)x,y=y,(x-(a//b)*y)return x,y,gcd n=3 nums=[[3,2],[5,3],[7,2]] while len(nums)>1:mid=nums.pop()a1,b1=mid[0],mid[1]mid=nums.pop()a2, b2 = mid[0], mid[1]mid1,mid2,mid3=ext_gcd(a1,a2)q=abs(b1-b2)mid1,mid2=mid1*(q/mid3),mid2*(q/mid3)k=mid1*a1+b1lcm=a1*a2/mid3nums.append([lcm,k]) print(int((mid1*a1+b1)%lcm))總結
以上是生活随笔為你收集整理的数论入门(python)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Live2D模型
- 下一篇: websocket python爬虫_p