P7328 「MCOI-07」Dream and Machine Learning
P7328 「MCOI-07」Dream and Machine Learning
给出一个 不依赖于
注意到
我们求出若干组这样的
由于
接下来考虑如何求出
笔者实现后发现时间瓶颈在于高精度快速幂,如果使用 FFT 优化和压位优化应该能跑得更快。求解
接下来说说这个做法相较于 std 可以扩展的地方。
首先它不依赖于
其次,它不太依赖于
唯一的问题在于这会使得
综上,本题可以加强至
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 5;
const int L = 600;
bool Mbe;
struct BigInt {
int len;
short a[L];
BigInt() {memset(a, 0, L << 1), len = 0;} // ADD len = 0
void print() {if(len) for(int i = len - 1; ~i; i--) putchar(a[i] + '0'); putchar('\n');}
void read() {
char s = getchar();
while(!isdigit(s)) s = getchar();
while(isdigit(s)) a[len++] = s - '0', s = getchar();
reverse(a, a + len);
}
void flush() {
len += 2;
for(int i = 0; i < len; i++) a[i + 1] += a[i] / 10, a[i] %= 10;
while(len && !a[len - 1]) len--;
}
void shrink() {
len += 2;
for(int i = 0; i < len; i++) if(a[i] < 0) a[i + 1]--, a[i] += 10;
while(len && !a[len - 1]) len--;
}
bool operator < (BigInt rhs) {
if(len != rhs.len) return len < rhs.len;
for(int i = len - 1; ~i; i--) if(a[i] != rhs.a[i]) return a[i] < rhs.a[i];
return 0;
}
BigInt operator + (BigInt rhs) {
BigInt res;
res.len = max(len, rhs.len);
for(int i = 0; i < res.len; i++) res.a[i] = a[i] + rhs.a[i]; // len -> res.len
res.flush();
return res;
}
BigInt operator - (BigInt rhs) {
BigInt res;
res.len = max(len, rhs.len);
for(int i = 0; i < res.len; i++) res.a[i] = a[i] - rhs.a[i];
res.shrink();
return res;
}
BigInt operator * (BigInt rhs) {
BigInt res;
res.len = len + rhs.len;
for(int i = 0; i < len; i++)
for(int j = 0; j < rhs.len; j++)
res.a[i + j] += a[i] * rhs.a[j];
res.flush();
return res;
}
BigInt operator * (int v) {
BigInt res;
res.len = len; // ADD THIS LINE
for(int i = 0; i < len; i++) res.a[i] = a[i] * v;
res.flush();
return res;
}
BigInt operator / (int v) {
BigInt res;
res.len = len;
int rem = 0;
for(int i = len - 1; ~i; i--) rem = rem * 10 + a[i], res.a[i] = rem / v, rem %= v;
while(res.len && !res.a[res.len - 1]) res.len--;
return res;
}
BigInt operator % (BigInt rhs) {
BigInt rem;
for(int i = len - 1; ~i; i--) {
rem = rem * 10, rem.a[0] += a[i], rem.flush();
while(!(rem < rhs)) rem = rem - rhs;
}
return rem;
}
} f[N], m, pw[32];
BigInt gcd(BigInt x, BigInt y) {
int pw = 0;
while(x.len && x.a[0] % 2 == 0 && y.len && y.a[0] % 2 == 0) pw++, x = x / 2, y = y / 2;
while(x.len && y.len) {
while(x.a[0] % 2 == 0) x = x / 2;
while(y.a[0] % 2 == 0) y = y / 2;
if(x < y) swap(x, y);
x = x - y;
}
if(x < y) swap(x, y);
while(pw--) x = x * 2;
return x;
}
int cnt = 20, b, n, q, e[N];
map <int, pair <int, int>> mp;
mt19937 rnd(time(0));
int rd(int l, int r) {return rnd() % (r - l + 1) + l;}
BigInt ksm(int b) {
BigInt s;
s.len = s.a[0] = 1;
int cnt = 0;
while(b) {
if(b & 1) s = s * pw[cnt] % m;
b >>= 1, cnt++;
}
return s;
}
void solve() {
pw[0].len = 1, pw[0].a[0] = b;
for(int i = 1; i < 30; i++) pw[i] = pw[i - 1] * pw[i - 1] % m;
while(q--) {
int a;
scanf("%d", &a);
ksm(a).print();
}
exit(0);
}
bool Med;
int main() {
fprintf(stderr, "%.4lf\n", (&Med - &Mbe) / 1048576.0);
// freopen("sample.in", "r", stdin);
cin >> b >> n >> q;
for(int i = 1; i <= n; i++) scanf("%d", &e[i]), f[i].read();
for(int i = 1; i <= 1e5; i++) {
int a = rd(1, n), b = rd(1, n);
mp[e[a] + e[b]] = make_pair(a, b);
}
for(int i = 1; i <= n; i++)
for(int j = 1; j <= n; j++) {
auto it = mp.find(e[i] + e[j]);
if(it == mp.end()) continue;
int a = it -> second.first, b = it -> second.second;
if(a == i || b == i) continue;
BigInt x = f[a] * f[b], y = f[i] * f[j];
if(x < y) swap(x, y);
m = gcd(m, x - y);
if(!--cnt) solve();
}
return 0;
}