LOJ2721 [NOI2018] 屠龍勇士 【擴展中國剩餘定理】

很久沒寫了,寫一篇湊個數。c++

題目分析:ui

這題不難想,講一下中國剩餘定理怎麼擴展。spa

考慮$$\left\{\begin{matrix}x \equiv a\pmod{b}\\ x \equiv c\pmod{d}\end{matrix}\right.$$code

不難發現須要知足$gcd(b,d)|(c-a)$纔有解。blog

結合後的模數必定是$lcm(b,d)$。而後擴展gcd合併就好了。it

中間過程會超過$10^18$,須要快速乘。ast

代碼:class

 1 #include<bits/stdc++.h>
 2 using namespace std;  3 
 4 const int maxn = 120000;  5 
 6 int n,m;  7 long long a[maxn],p[maxn],LP[maxn],d[maxn];  8 
 9 multiset<long long,greater<long long> > s; 10 
11 long long cut[maxn],minn; 12 long long st[maxn],f[maxn]; 13 
14 void init(){ 15     s.clear();memset(st,0,sizeof(st)); memset(f,0,sizeof(f)); 16     for(int i=1;i<=m;i++) s.insert(d[i]); 17     for(int i=1;i<=n;i++){ 18     set<long long>::iterator it = s.lower_bound(a[i]); 19     if(it == s.end())it--;    cut[i] = (*it); 20  s.erase(it); s.insert(LP[i]); 21  } 22     minn = 0; 23     for(int i=1;i<=n;i++) minn = max(minn,(long long)ceil((double)a[i]/cut[i])); 24 } 25 
26 long long exgcd(long long alpha,long long beta,long long &x,long long &y){ 27     if(beta == 0){x = 1; y = 0; return alpha;} 28     else{ 29     long long res = exgcd(beta,alpha%beta,y,x); 30     y-=x*(alpha/beta); 31     return res; 32  } 33 } 34 
35 void read(){ 36     scanf("%d%d",&n,&m); 37     for(int i=1;i<=n;i++) scanf("%lld",&a[i]); 38     for(int i=1;i<=n;i++) scanf("%lld",&p[i]); 39     for(int i=1;i<=n;i++) scanf("%lld",&LP[i]); 40     for(int i=1;i<=m;i++) scanf("%lld",&d[i]); 41 } 42 
43 long long multi(long long alpha,long long beta,long long mod){ 44     long long dt,bit = 1,ans = 0; 45     alpha %= mod; beta %= mod; 46     alpha += mod; beta += mod; 47     alpha %= mod; beta %= mod; 48     dt = alpha; 49     while(bit <= beta){ 50     if(bit & beta){ans += dt; if(ans >= mod) ans -= mod;} 51     bit<<=1;dt = (dt+dt); if(dt >= mod) dt -= mod; 52  } 53     return ans; 54 } 55 
56 int cntt = 0; 57 void work(){ 58     for(int i=1;i<=n;i++){ 59     long long hd = exgcd(cut[i],p[i],st[i],f[i]); 60     if(a[i] % hd != 0){puts("-1");return;} 61     f[i] = p[i]/hd; st[i] %= f[i]; if(st[i] < 0) st[i] += f[i]; 62     st[i] = multi(st[i],a[i]/hd,f[i]); st[i] %= f[i]; 63  } 64     for(int i=2;i<=n;i++){ 65     long long im = exgcd(f[i],f[i-1],f[0],f[0]); 66     if((st[i]-st[i-1])%im){ 67         puts("-1");return; 68  } 69     long long um = f[i]/im*f[i-1]; 70     long long tf=0; exgcd(f[i-1],f[i],tf,f[0]); 71     tf =multi(tf,(st[i]-st[i-1])/im,um); 72     tf += (-tf/f[i])*f[i]; tf += f[i]; 73     tf = (st[i-1]+multi(tf,f[i-1],um))%um; 74     if(tf < 0) tf += um; 75     f[i] = um; st[i] = tf; 76  } 77     if(st[n] < minn){ 78     st[n] += (minn-st[n])/f[n]*f[n]; 79  } 80     printf("%lld\n",st[n]); 81     //fast multi
82 } 83 
84 int main(){ 85     int Tmp; scanf("%d",&Tmp); 86     while(Tmp--){ 87     cntt++; 88  read(); 89  init(); 90  work(); 91  } 92     return 0; 93 }
相關文章
相關標籤/搜索
本站公眾號
   歡迎關注本站公眾號,獲取更多信息