数论练习1 ( 曹冲养猪 + [POJ 2891]Strange Way to Express Integers + 乘法逆元【带证明】)
雖然作業還沒有做完,但是我還是放不下它,對此,我只想說:
今天你對作業愛理不理,明天它就讓你補到飛起
DP先放放,我們要雨露均沾
- 練習上手:乘法逆元
- 題目
- 題解
- 代碼實現
- 曹沖養豬?(互質的中國剩余定理)
- 題目
- 題解
- 代碼實現
- Strange Way to Express Integers(不互質的中國剩余定理)
- 題目
- 題解
- 代碼實現
練習上手:乘法逆元
題目
題解
對于這種求[1,n]區間的乘法逆元,
費馬小定理?
擴展歐幾里得?
這兩種對于求單個是比較有用的,O(nlogn)
但是對于這種區間求解就需要O(n)的線性篩了
至于為什么是這樣子的,我們來進行簡單推理:
首先應該要了解
對于數字A,B存在A?X≡1(modBA*X≡1(mod BA?X≡1(modB),則稱X為A對B的逆元。
一般這個乘法逆元是運用在需要取模而過程中又涉及到除法運算的時候,
將其轉化為乘法計算
進入證明?:
記T=p/i,K=pT=p/i,K=pT=p/i,K=p%iii
則有K+T?i=pK+T*i=pK+T?i=p,被除數等于商乘除數加余數
即K+T?i≡0(modK+T*i≡0 (modK+T?i≡0(mod p)p)p)
變形:K≡?T?i(modK≡-T*i(modK≡?T?i(mod p)p)p)
兩邊同時除以i?Ki*Ki?K
–>1/i≡?T/K(mod1/i≡-T/K(mod1/i≡?T/K(mod p)p)p)
1/i1/i1/i就是i的逆元,
因為這兩個相乘取模p同余1,同時:除以K就相當于乘以K的逆元
接下來,將T=p/i,K=pT=p/i,K=pT=p/i,K=p%iii帶入進去?
inv[i]=?p/i?inv[pinv[i]=-p/i*inv[pinv[i]=?p/i?inv[p%i]i]i](mod p)p)p)
為了防止出現負數,就加一個p?inv[pp * inv[pp?inv[p%i]i]i],利用取模的運算律
inv[i]=inv[pinv[i] = inv[pinv[i]=inv[p%i]?(p?p/i)i] * ( p - p / i )i]?(p?p/i)%ppp
代碼實現
#include <cstdio> #define LL long long #define MAXN 3000005 int n, p; LL inv[MAXN]; int main() {scanf ( "%d %d", &n, &p );inv[1] = 1;printf ( "1\n" );for ( int i = 2;i <= n;i ++ ) {inv[i] = inv[p % i] * ( p - p / i ) % p;printf ( "%lld\n", inv[i] );}return 0; }ok,讓我們隨著難度的增加慢慢深入,就先去養養?,體驗農村生活
曹沖養豬?(互質的中國剩余定理)
題目
題解
這道題,還好還好,麻痹自己,模板也是可以自己,慢慢看懂的,我就不多證明了,
主要是我懶得打了。。。
取模定理:兩數不能整除,若被除數擴大(或縮小)了幾倍,而除數不變,則其商和余數也同時擴大(或縮小)相同的倍數(余數必小于除數)。
如果a%b=c,那么如果x%b=c * 2,此時有x=a * 2;
轉化為求通解問題,即:
求解同余方程組
x≡ a1?(mod m1?)
x≡ a2?(mod m2?)
x≡ a3?(mod m3?)
…
x≡ ak?(mod mk?)?
其中m1,m2,m3…mk為兩兩互質的整數求x的最小非負整數解
M是輸入的所有m[i]的乘積,Ti是M/mi的逆元
接下來就是模板套上去就可以了,在這里我只想補充,int128是個好玩意兒啊!!
代碼實現
#include <cstdio> #define MAXN 15 #define LL __int128 int n; int m[MAXN], r[MAXN];void print ( LL x ) {if ( x > 9 )print ( x / 10 );putchar ( ( x % 10 ) + '0' ); }void exgcd ( LL a, LL b, int &x, int &y ) {if ( ! b ) {x = 1;y = 0;return;}exgcd ( b, a % b, y, x );y -= ( a / b ) * x; } int main() {scanf ( "%d", &n );for ( int i = 1;i <= n;i ++ )scanf ( "%d %d", &m[i], &r[i] );LL lcm = 1, ans = 0;int x, y;for ( int i = 1;i <= n;i ++ )lcm = lcm * m[i];for ( int i = 1;i <= n;i ++ ) {LL tp = lcm / m[i];exgcd ( tp, m[i], x, y );x = ( x % m[i] + m[i] ) % m[i];ans = ( ans % lcm + tp * r[i] % lcm * x % lcm ) % lcm;}LL res = ( ans % lcm + lcm ) % lcm;print ( res );return 0; }Strange Way to Express Integers(不互質的中國剩余定理)
題目
題解
那么,當模數不兩兩互質
即求:
解同余方程組
x≡ a1?(mod m1?)
x≡ a2?(mod m2?)
x≡ a3?(mod m3?)…
x≡ ak?(mod mk?)?
其中m1,m2,m3…mk是不一定兩兩互質的整數求x的最小非負整數解
我們先考慮:只有兩個數該怎么處理
可以得到:
x=a1+k1?m1x=a1+k1*m1x=a1+k1?m1
x=a2+k2?m2x=a2+k2*m2x=a2+k2?m2
k2?m2?k1?m1=a1?a2k2*m2-k1*m1=a1-a2k2?m2?k1?m1=a1?a2
四不四很像 ax+by=cax+by=cax+by=c
設m1,m2的gcd為g,a1?a2=ca1-a2=ca1?a2=c
1)當c不是g的倍數時,exgcd無解
2)如果是,
則用exgcd求出k2?m2+(?k1)?m1=gcd(m1,m2)k2*m2+(-k1)*m1=gcd(m1,m2)k2?m2+(?k1)?m1=gcd(m1,m2)
因為c是g的倍數,兩邊同時乘以一個c/g,即k1乘上c/g得到
k2?m2+(?k1)?m1=c解為?k1k2*m2+(-k1)*m1=c解為-k1k2?m2+(?k1)?m1=c解為?k1
X=a1?k1?m1X=a1-k1*m1X=a1?k1?m1
這樣就求出了x。
我們設這個x為x0
所以,可以得到的通解為x=x0+k?lcm(m1,m2)x=x0+k*lcm(m1,m2)x=x0+k?lcm(m1,m2)
將這個方程轉化一下,可以得到一個新的同余方程
x=x0(modx=x0(modx=x0(mod lcm(m1,m2))lcm(m1,m2))lcm(m1,m2))
我們便成功的將兩個方程轉化為了一個方程
后面以此類推,得到最后一個x0,即為我們所需要的答案。
上模板講解?
M是上一次的最小公倍數lcm
R是上一次的x0,及我們的當前答案
代碼實現
#include <cstdio> #define MAXN 100005 #define LL long long int n; int m[MAXN], a[MAXN];LL exgcd ( LL a, LL b, LL &x, LL &y ) {if ( ! b ) {x = 1;y = 0;return a;}LL d = exgcd ( b, a % b, y, x );y -= ( a / b ) * x;return d; } LL gcd, R, M, x, y, c;int main() {while ( scanf ( "%d", &n ) != EOF ) {bool flag = 0;for ( int i = 1;i <= n;i ++ )scanf ( "%d %d", &m[i], &a[i] );R = a[1], M = m[1];for ( int i = 2;i <= n;i ++ ) {gcd = exgcd ( M, m[i], x, y );c = R - a[i];if ( c % gcd ) {flag = 1;printf ( "-1\n" );break;}x = c / gcd * x % ( m[i] / gcd );R -= x * M;M = M / gcd * m[i];R %= M;}if ( ! flag )printf ( "%lld\n", ( R % M + M ) % M );} return 0; }好了,我已經被榨干了,去做其他的DP和數論了,ヾ( ̄▽ ̄)ByeBye
總結
以上是生活随笔為你收集整理的数论练习1 ( 曹冲养猪 + [POJ 2891]Strange Way to Express Integers + 乘法逆元【带证明】)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 骁龙 695:vivo 新机 Y100
- 下一篇: AMD RX 6300 入门独显上市:搭