51nod1079(中國剩余定理)


題目鏈接: http://www.51nod.com/onlineJudge/user.html#!userId=21687

 

題意: 中文題誒~

 

思路: 本題就是個中國剩余定理模板題,不過模擬也可以過,而且時間復雜度嘛~

我們可以知道gcd得出兩個數的最大公約在最壞的情況下(a, b是相鄰的兩個斐波拉契數)是O(logn)的, 同理可以知道exgcd也是O(lgn)時間復雜度,因此中國剩余定理時間復雜度是O(nlogn); 而模擬的話最壞的情況下需要O(n*x)的時間~本題兩種算法都是15ms...

這里給出一個關於gcd時間復雜度分析的博客: http://blog.csdn.net/zeroonet/article/details/53375313

 

我們先說一下模擬.首先我們知道如果x%a=m的話, x=k*a+m.

對於 x%a1=m1, 很顯然x(min)=m, 如果再加一組條件 x%a2=m2, 若當前x(min)不滿足條件2的話, 我們找下一個(我們可以想象滿足條件1的數據升序排列)滿足條件1的數據,即a1+m,再判斷其是否滿足條件2, 很顯然我們只要地推下去就能找到同時滿足條件1, 2的最小數據; 如果再加一個條件 x%a3=m3呢? 前面我們已經招到了滿足條件1, 2的最小數據

x(min), 若其不滿足條件3話, 我們找下一個滿足條件1, 2的數據, 即x(min)+lcm(a1, a2)(此題中ai與aj互質,所以直接相乘就好啦,並且由這里我們不難看出最壞情況下即每次加2時其時間復雜度為O(x)), 再判斷其是否滿足條件3, 最終我們可以招到同時滿足三個條件的最小數;

那么,很明顯對於要滿足n個這樣的條件的答案我們也可以用這個方法求到啦~

代碼:

 1 #include <bits/stdc++.h>
 2 #define MAXN 20
 3 #define ll long long
 4 using namespace std;  5 
 6 int main(void){  7     int n;  8     ll p[MAXN], m[MAXN], ans=0, gg=1;  9     scanf("%d", &n); 10     for(int i=0; i<n; i++){ 11         scanf("%lld%lld", &m[i], &p[i]); 12  } 13     ans=p[0]; 14     for(int i=0; i<n-1; i++){ 15         gg*=m[i]; 16         while(ans%m[i+1]!=p[i+1]){ 17             ans+=gg; 18  } 19  } 20     printf("%lld\n", ans); 21     return 0; 22 }

 

那么中國剩余定理的模板呢~

至於證明嘛, 暫時還沒想到(望路過的大神教一下)~

 

代碼:

 1 #include <bits/stdc++.h>
 2 #define MAXN 20
 3 #define ll long long
 4 using namespace std;  5 
 6 ll p[MAXN], m[MAXN];  7 int n;  8 
 9 void exgcd(ll a, ll b, ll& x, ll& y){ //exgcd求乘法取模運算的逆元 10     if(!b){ 11         y=0, x=1; 12         return; 13     }else{ 14         exgcd(b, a%b, x, y); 15         ll temp=x; 16         x=y; 17         y=temp-a/b*y; 18  } 19 } 20 
21 ll crt(void){ 22     ll M=1, ans=0; 23     for(int i=0; i<n; i++){ 24         M*=m[i]; 25  } 26     for(int i=0; i<n; i++){ 27         ll mi=M/m[i], x, y; 28  exgcd(mi, m[i], x, y); 29         ans=(ans+p[i]*x*mi)%M; 30  } 31     if(ans<0){ 32         ans+=M; 33  } 34     return ans; 35 } 36 
37 int main(void){ 38     scanf("%d", &n); 39     for(int i=0; i<n; i++){ 40         scanf("%lld%lld", &m[i], &p[i]); 41  } 42     printf("%lld\n", crt()); 43     return 0; 44 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM