猜数字

现有两组数字,每组k个,第一组中的数字分别为:a1,a2,...,ak表示,第二组中的数字分别用b1,b2,...,bk表示。其中第二组中的数字是两两互素的。求最小的非负整数n,满足对于任意的i,n - ai能被bi整除。

中国剩余定理,要注意对a[i]为负数时的处理

还要注意快速乘法,因为可能溢出导致答案错误

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
typedef long long ll;
ll k,a[17],b[17];
ll exgcd(ll a,ll b,ll &x,ll &y){
  if(b==0){
    x=1;y=0;return a;
  }
  else{
    ll d=exgcd(b,a%b,y,x);
    y-=(a/b)*x;
    return d;
  }
}
ll qmul(ll a,ll b,ll mod){
  ll ret=0;
  for(;b;b>>=1,a=(a+a)%mod){
    if(b&1) ret+=a;
  } 
  return ret;
} 
ll lmes(){
  ll tmp=1,m,mf,y,ret=0;;
  for(ll i=1;i<=k;i++) tmp*=b[i];
  for(ll i=1;i<=k;i++){
    m=tmp/b[i];
    ll k=exgcd(m,b[i],mf,y);
    mf=(mf%b[i]+b[i])%b[i];
    ret=(ret+qmul(qmul(a[i],m,tmp),mf,tmp))%tmp;
  }
  return (ret+tmp)%tmp;
}
int main(){
  cin>>k;
  for(ll i=1;i<=k;i++) cin>>a[i];
  for(ll i=1;i<=k;i++) cin>>b[i];
  for(ll i=1;i<=k;i++) a[i]=(a[i]%b[i]+b[i])%b[i];
  cout<<lmes()<<endl;
  return 0;
}

 

posted @ 2018-10-17 13:53  lcan  阅读(266)  评论(0编辑  收藏  举报