luogu P3868 【[TJOI2009]猜数字】
刚学CRT,来发一篇题解。
切入正题
很显然,对于每个
\[b_i | (n-a_i)
\]
都等价于
\[n \equiv a_i \ (mod\ b_i)
\]
所以这\(k\)个式子,就转化成了中国剩余定理的模型。
套板子即可。
然后你会发现WA90
因为所有\(b_i\)乘起来最大是\(10^{18}\),所以再乘其他数就会爆long long。
怎么破?
可以用__int128
或 快(龟)速乘。
由于我懒(其实是不会龟速乘),就打了_int128
。
\(Code\):
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
#define int __int128
template<class T>inline void read(T &x){
x=0;
register int f=0,ch=getchar();
while('0'>ch||ch>'9')f^=ch=='-',ch=getchar();
while('0'<=ch&&ch<='9')x=(x<<3)+(x<<1)+(ch^'0'),ch=getchar();
x=f?-x:x;
}
template<class T>inline void print(T x){
if(x<0)putchar('-'),x=-x;
if(x>9)print(x/10);
putchar(x%10+'0');
}
const int MAX=15;
int n,M=1,m,p[MAX],a[MAX],inv,ans;
void exgcd(int a,int b,int &x,int &y){
if(b==0){x=1,y=0;}
else {
exgcd(b,a%b,x,y);
register int t=x;x=y;y=t-a/b*y;
}
}
int res;
int x,y;
inline int CRT(){
for(register int i=1;i<=n;++i){
m=M/p[i];x=y=0;
exgcd(m,p[i],x,y);
ans=(ans+m%M*x%M*a[i]%M)%M;
}
ans=(ans%M+M)%M;
return ans;
}
signed main(){
read(n);
for(register int i=1;i<=n;++i)read(a[i]);
for(register int i=1;i<=n;++i)read(p[i]),M*=p[i];
print(CRT()%M);
return 0;
}