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;
}


posted @ 2020-03-01 17:04  Lates  阅读(150)  评论(0)    收藏  举报