思路
中國剩餘定理 + 快速乘
題目要求找到最小的,滿足對於,有
我們試着來轉化一下這個式子
,也就是說在模意義下同餘,即,進一步轉化,就能得到
這個式子是不是很眼熟?沒錯,就是中國剩餘定理的式子,因爲題目中已經保證了兩兩互素,所以我們就可以直接套中國剩餘定理的板子了
設,,是線性同餘方程的一個解(即的逆元),最後的解即爲
那麼這樣就完了嘛?
此題終結其實不然
這樣交上去之後,會發現只有九十分,最後一個點了,因爲這題要用快速乘,於是寫上快速乘
那麼這樣就完了嘛?
此題終結其實也不然
又交上去之後,發現還是九十分,不過這次錯的點是第二個了。
這是爲什麼呢?
看題目條件:
什麼意思呢?意思就是可能是負的!(出題人真是用心良苦
處理的方法就是:快速乘傳參時取模
那麼這樣就完了嘛?
興沖沖的交上去,終於滿分了,沒錯,這次真完了
代碼
/*
Author:loceaner
中國剩餘定理板子題
*/
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define int long long
using namespace std;
const int A = 5e5 + 11;
const int B = 1e6 + 11;
const int mod = 1e9 + 7;
const int inf = 0x3f3f3f3f;
inline int read() {
char c = getchar(); int x = 0, f = 1;
for( ; !isdigit(c); c = getchar()) if(c == '-') f = -1;
for( ; isdigit(c); c = getchar()) x = x * 10 + (c ^ 48);
return x * f;
}
int n, N = 1, b[A], a[A], ans;
inline int mul(int n, int m, int mod) {
int res = 0;
while (m) {
if (m & 1) res = (res + n) % mod;
n = (n + n) % mod, m >>= 1;
}
return res;
}
inline void exgcd(int a, int b, int &x, int &y) {
if (!b) x = 1, y = 0;
else exgcd(b, a % b, y, x), y -= a / b * x;
}
signed main() {
n = read();
for (int i = 1; i <= n; i++) a[i] = read();
for (int i = 1; i <= n; i++) b[i] = read(), N *= b[i];
for (int i = 1; i <= n; i++) {
int x, y, Mi = N / b[i];
exgcd(Mi, b[i], x, y);
ans = (ans + mul(mul(Mi, x % N + N, N), a[i] % N + N, N) % N + N) % N;
}
cout << ans % N << '\n';
return 0;
}