中国剩余定理
2道模板题:
[TJOI2009]猜数字
// luogu-judger-enable-o2
#include<bits/stdc++.h>
using namespace std;
#define R register int
#define AC 15
#define db double
#define LL long long
int k; LL M = 1, ans, tmp;
LL m[AC], a[AC], t[AC];
inline int read()
{
int x = 0;char c = getchar();bool z = false;
while(c > '9' || c < '0') {if(c == '-') z = true; c = getchar();}
while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
if(!z) return x;
else return -x;
}
void exgcd(LL a, LL b, LL &x, LL &y)
{
if(!b) x = 1, y = 0;
else exgcd(b, a % b, y, x), y -= (a / b) * x;
}
inline void up(LL &a, LL b) {a = (a + b) % M;}
inline LL ad(LL x, LL have)
{
LL rnt = 0;
while(have)
{
if(have & 1) up(rnt, x);
up(x, x), have >>= 1;
}
return rnt;
}
#define int long long
int Mul(int x, int y){
return (x * y - (int) (((db) x * y + 0.5) / (db) M)* M + M) % M;
}
#undef int
void pre()
{
k = read();
for(R i = 1; i <= k; i ++) a[i] = read();
for(R i = 1; i <= k; i ++) m[i] = read(), M *= m[i];
for(R i = 1; i <= k; i ++) a[i] = (a[i] % m[i] + m[i]) % m[i];
}
void work()
{
for(R i = 1; i <= k; i ++)
{
exgcd(M / m[i], m[i], t[i], tmp);
up(ans, Mul(Mul(a[i], M / m[i]), t[i]));
}
printf("%lld\n", (ans % M + M) % M);
}
int main()
{
// freopen("in.in", "r", stdin);
pre();
work();
// fclose(stdin);
return 0;
}
// luogu-judger-enable-o2
#include<bits/stdc++.h>
using namespace std;
#define R register int
#define AC 101000
#define ld long double
#define LL long long
int n;
LL c[AC], m[AC];
inline LL read()//读入开LL
{
LL x = 0;char c = getchar();
while(c > '9' || c < '0') c = getchar();
while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
return x;
}
void pre()
{
n = read();
for(R i = 1; i <= n; i ++) m[i] = read(), c[i] = read();
}
void exgcd(LL a, LL b, LL &x, LL &y)
{
if(!b) x = 1, y = 0;
else exgcd(b, a % b, y, x), y -= (a / b) * x ;
}
inline LL gcd(LL x, LL y)
{
for(LL t; y; t = x, x = y, y = t % x);
return x;
}
LL mul(LL a, LL b, LL p)//O(1)快速乘
{
a %= p, b %= p;
LL t = (ld) a * b / p;
LL r = a * b - p * t;
if (r < 0) r += p;
return r;
}
void EXCRT()
{
LL C = c[1], M = m[1], inv;
for(R i = 2; i <= n; i ++)
{
LL t = gcd(m[i], M), p = M / t, now = M, k = m[i] / t;
M = M / t * m[i];//先除再乘防止爆LL
exgcd(p, m[i] / t, inv, m[0]), inv = (inv % k + k) % k;//求出m1 / t在m2 / t意义下的逆元
C = (mul(mul((c[i] - C) / t, inv, M), now, M) + C) % M;
//printf("%lld %lld\n", C, M);
}
LL ans = (C % M + M) % M;
printf("%lld\n", ans);
}
int main()
{
// freopen("in.in", "r", stdin);
pre();
EXCRT();
// fclose(stdin);
return 0;
}