当年,我写CRT时,因为没有写快速乘而T了一个点,
现在,我写EXCRT,快速乘毛线都没有,然后AC了。
Code:
#include<bits/stdc++.h>
#define TEST_TIME 10
#define POLLAR_K 127
#define ll long long
#define ui unsigned int
using namespace std;
#define gint __int128
namespace Pollard_Rho{
ll gcd(ll a,ll b){
if(b==0)return a;
return gcd(b,a%b);
}
ll f(ll x,ll c,ll n){
return ((gint)x*x+c)%n;
}
ll pollardRho(ll pr){
ll s=0,t=0,c=rand()%(pr-1)+1,val=1;
int step=0,goal=1;
for(goal=1;;goal*=2,s=t,val=1){
for(step=1;step<=goal;step++){
t=f(t,c,pr);
val=(gint)val*abs(t-s)%pr;
if((step%POLLAR_K)==0){
ll d=gcd(val,pr);
if(d>1)return d;
}
}
ll d=gcd(val,pr);
if(d>1)return d;
}
}
}
namespace Miller_Rabin{
ll qp(ll a,ll b,ll p){
ll ans=1,base=a;
while(b){
if(b&1){ans=(gint)ans*base%p;}
base=(gint)base*base%p;
base%=p;
b>>=1;
}
return ans;
}
bool millerRabin(ll pr){
if(pr<2)return 0;
if(pr==3)return 1;
if(pr==2)return 1;
ll a=pr-1,b=0;
while(!(a&1))a>>=1,b++;
for(int i=1;i<=TEST_TIME;i++){
ll x=rand()%(pr-2)+2,v=qp(x,a,pr),j;
if(v==1||v==pr-1)continue;
for(j=0;j<b-1;j++){
v=(gint)v*v%pr;
if(v==pr-1)break;
}
if(v!=pr-1)return false;
}
return true;
}
}
namespace Divide_Number{
ll max_factor;
using namespace Miller_Rabin;
using namespace Pollard_Rho;
void fac(ll x){
if(x<=max_factor||x<2)return;
if(millerRabin(x)){
max_factor=max(max_factor,x);
return;
}
ll p=x;
while(p>=x)p=pollardRho(x);
while((x%p)==0)x/=p;
fac(x),fac(p);
}
}
namespace Sieve{
#define MAXN_A 50005
ll mu[MAXN_A];
ll sumMu[MAXN_A];
ll p[MAXN_A];
bool ip[MAXN_A];
ll pcnt;
void get(int n){
mu[1]=1;
pcnt=0;
for(int i=2;i<=n;i++){
if(!ip[i]){
p[++pcnt]=i;
mu[i]=-1;
}
for(int j=1;j<=pcnt&&i*p[j]<=n;j++){
ip[i*p[j]]=1;
if(i%p[j]==0){
mu[i*p[j]]=0;
break;
}
mu[i*p[j]]=-mu[i];
}
}
}
void init_sumMu(int n){
get(n);
for(int i=1;i<=n;i++){
sumMu[i]=sumMu[i-1]+mu[i];
}
}
}
namespace Divide_Of_Maths{
using namespace Sieve;
ll h(ll n,ll k){
ll l=1,r,an=0;
n=min(n,k);
while(l<=n){
if(k/l!=0)
r=min(n,k/(k/l));
else
r=n;
an+=(r-l+1)*(k/l)*(l+r)/2;
l=r+1;
}
return an;
}
ll solve(ll n,ll k){
ll l=1,r,ans=0;
for(;l<=min(n,k);l=r+1){
r=min(n/(n/l),k/(k/l));
ans+=(sumMu[r]-sumMu[l-1])*(n/l)*(k/l);
}
return ans;
}
ll getRegionalGcd(ll a,ll b,ll c,ll d,ll k){
return solve(b/k,d/k)-
solve(b/k,(c-1)/k)-
solve((a-1)/k,d/k)+
solve((a-1)/k,(c-1)/k);
}
}
namespace Basic_Maths_Theory{
gint gcd(gint a,gint b){
if(b==0)return a;
return gcd(b,a%b);
}
gint lcm(gint a,gint b){
return ((gint)(a))*b/gcd(a,b);
}
gint ex_gcd(gint a,gint b,gint &x,gint &y){
if(b==0){
x=1;
y=0;
return a;
}
else{
gint r=ex_gcd(b,a%b,x,y);
gint t=x;
x=y;
y=t-a/b*y;
return r;
}
}
gint get_remainder_alpha_solu(gint a,gint b,gint c){
gint x,y;
gint d=ex_gcd(a,c,x,y);
if(b%d!=0)return -LONG_LONG_MAX;
gint e=c/d,ans;
ans=x*(b/d)%c;
ans=(ans%e+e)%e;
return ans;
}
}
namespace EXCRT_{
#define MAXN_B 100010
using namespace Basic_Maths_Theory;
ll a[MAXN_B],m[MAXN_B];
gint EXCRT(ll n){
gint b=a[1],M=m[1];
for(int i=2;i<=n;i++){
gint x,y;
gint tmp1=((a[i]-b)%m[i]+m[i])%m[i];
gint tmp2=get_remainder_alpha_solu(M,tmp1,m[i]);
gint nM=lcm(M,m[i]);
b=(M*tmp2%nM+b)%nM;
M=nM;
}
return b;
}
}
using namespace EXCRT_;
int main(){
ll n;
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%lld%lld",&m[i],&a[i]);
}
cout<<(ll)EXCRT(n);
}
不要被码风恶心到qwq