日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

3811乘法逆元

發布時間:2024/1/1 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 3811乘法逆元 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

目錄

題目(來源洛谷3811)

逆元定義

求逆元的幾種方法

一、拓展歐幾里得版

二、快速冪(分治思想)

遞歸快速冪

非遞歸快速冪

三、線性算法

“碎碎念”


題目(來源洛谷3811)

題目背景

這是一道模板題

題目描述

給定?n,p?求 1~n?中所有整數在模?p?意義下的乘法逆元。

輸入格式

一行兩個正整數?n,p。

輸出格式

輸出?n?行,第?i?行表示?i?在模?p?下的乘法逆元。

樣例

輸入

10 13

輸出

1 7 9 10 8 11 2 5 3 4

說明

1 ?n??,n < p < 20000528

輸入保證?p?為質數。

(((這題貌似只能用第三種線性的方法過哈,其它的會超時...

逆元定義

若 a ? x ≡ 1(mod b),且a與b互質,那么我們就能定義:?x?為?a?的逆元,記為,所以我們也可以稱?x為?a?在?mod b?意義下的倒數,

所以對于 ??(mod p)?,我們就可以求出?b?在?mod p?下的逆元,然后乘上?a?,再?mod p,就是這個分數的值了。

求逆元的幾種方法

一、拓展歐幾里得版

單個查找效率不錯,比大部分方法要快(尤其對于mod p 比較大的時候)

好處就是,當ap(互質),但p不是質數的時候也可以使用。

【不要問我為什么不解釋,懂的人覺得“十分容易理解”,很不幸,我個fw不懂,先就背下來完事兒叭qwq】

#include<stdio.h> typedef long long ll; void Exgcd(ll a, ll b, ll &x, ll &y){ // &x 為"引用",可理解為//在其它函數內也能改變main里的變量,沒有指針那么麻煩 if(!b) x = 1, y = 0;else Exgcd(b, a%b, y, x), y-=a/b*x; } int main(){ll x, y, n, p,a;scanf("%lld %lld",&n,&p);for(int i=1;i<=n;i++){a=i;Exgcd(a, p, x, y);x = (x%p+p)%p;printf("%lld\n",x); //x是a在mod p下的逆元} }

二、快速冪(分治思想)

快速冪Exponentiation by squaring,平方求冪) 是一種簡單而有效的小算法,它可以以O(log n)的時間復雜度計算乘方。

讓我們先來思考一個問題:7的10次方,怎樣算比較快?

方法1:最樸素的想法,7*7=49,49*7=343,... 一步一步算,共進行了9次乘法。

這樣算無疑太慢了,尤其對計算機的CPU而言,每次運算只乘上一個個位數,無疑太屈才了。這時我們想到,也許可以拆分問題。

方法2:先算7的5次方,即7*7*7*7*7,再算它的平方,共進行了5次乘法。

但這并不是最優解,因為對于“7的5次方”,我們仍然可以拆分問題。

方法3:先算7*7得49,則7的5次方為49*49*7,再算它的平方,共進行了4次乘法。

模仿這樣的過程,我們得到一個在?O(log n)?時間內計算出冪的算法,也就是快速冪。

即二分思路,可得

遞歸快速冪

int qpow(int a, int n){if (n == 0) return 1;else if (n % 2 == 1)return qpow(a, n - 1) * a;else{int temp = qpow(a, n / 2); //注意這個temp變量是必要的return temp * temp; } }

注意上述代碼中temp變量是必要的,否則若寫成qpow(a, n /2)*qpow(a, n /2),那就會計算兩次,整個算法就退化為了O(n)?.

遞歸雖然簡潔,但會產生額外的空間開銷。我們可以把遞歸改寫為循環,來避免對棧空間的大量占用,也就是

非遞歸快速冪

我們將指數轉換為二進制的形式:??又發現(8=)即

?先只是冪 的代碼好理解:

//非遞歸快速冪 int qpow(int a, int n){int ans = 1;while(n){if(n&1) //如果n的當前末位為1ans *= a; //ans乘上當前的aa *= a; //a自乘n >>= 1; //n往右移一位}return ans; }

前期預備了下快速冪?的原理,接下來了解下此處要用到的費馬小定理

p為素數,a為正整數,且a、p互質。 則有?≡ 1(mod p)。式 子右邊恰好為1;

所以我們就可以放入原式,就可以得到:

a ? x ≡ 1(mod p)

a ? x ≡ (mod p)

x ≡ ?(mod p)

所以我們可以用快速冪來算出??(mod p)的值,這個數就是它的逆元了

【理解了之前的代碼,再看這個加上模除的代碼應該就好理解了(順帶簡化了下bushi】

#include<stdio.h> typedef long long ll; ll n, p; ll qpow(ll x ,ll pow, ll mod){ll ans = 1;for(; pow; pow>>=1, x = x * x % mod)if(pow & 1) ans = ans * x % mod;return ans; } int main(){scanf("%d %d",&n,&p);for(int i=1;i<=n;i++){ll x = qpow(i,p-2,p);printf("%lld\n",x);}return 0; }

三、線性算法

用于求一連串數字對于一個mod p的逆元。

只能用這種方法,別的算法都比這些要求一串要慢。

【核心代碼也就一行,窩理解不了,背叭QWQ】

#include<stdio.h> long long inv[3000006]; int main(){long long n,p;int i;scanf("%lld %lld",&n, &p); inv[1]=1;printf("1\n");for(i=2; i<=n; i++){inv[i]=(p-p/i)*inv[p%i]%p;printf("%lld\n",inv[i]);}return 0; }

“碎碎念”

就是說,模糊的代碼要多看一看、查一查、敲一敲,(說不定突然就理解了呢QWQ)比如窩這次看快速冪的方法,就由原來的一點不懂到差不多懂了(bushi)。特地整理一下,方便(有需要的uu們和)窩再看(我知道大佬們覺得賊簡單,但我是真的是"一看就忘"型QWQ)

總結

以上是生活随笔為你收集整理的3811乘法逆元的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。