QOJ.ac
QOJ
ID | Problem | Submitter | Result | Time | Memory | Language | File size | Submit time | Judge time |
---|---|---|---|---|---|---|---|---|---|
#468390 | #3799. It's Surely Complex | PetroTarnavskyi | WA | 2ms | 5668kb | C++20 | 6.2kb | 2024-07-08 20:35:44 | 2024-07-08 20:35:45 |
Judging History
answer
#include <bits/stdc++.h>
using namespace std;
#define FOR(i, a, b) for(int i = (a); i < (b); i++)
#define RFOR(i, a, b) for(int i = (a) - 1; i >= (b); i--)
#define SZ(a) int(a.size())
#define ALL(a) a.begin(), a.end()
#define PB push_back
#define MP make_pair
#define F first
#define S second
typedef long long LL;
typedef vector<int> VI;
typedef pair<int, int> PII;
typedef __float128 db;
typedef unsigned long long ULL;
int p;
ULL mod = 9223372036737335297;
const int LEN = 1 << 21;
ULL add(ULL a, ULL b)
{
return a + b < mod ? a + b : a + b - mod;
}
ULL sub(ULL a, ULL b)
{
return a >= b ? a - b : a + mod - b;
}
ULL mult(ULL a, ULL b)
{
return (__int128)a * b % mod;
}
ULL binpow(ULL a, ULL n)
{
ULL res = 1;
while (n)
{
if (n & 1)
res = mult(res, a);
a = mult(a, a);
n /= 2;
}
return res;
}
const ULL GEN = binpow(3, (mod - 1) / LEN);
const ULL IGEN = binpow(GEN, mod - 2);
void fft(vector<ULL>& a, bool inv)
{
int lg = __builtin_ctz(SZ(a));
FOR(i, 0, SZ(a))
{
int k = 0;
FOR(j, 0, lg)
k |= ((i >> j) & 1) << (lg - j - 1);
if (i < k)
swap(a[i], a[k]);
}
for (int len = 2; len <= SZ(a); len *= 2)
{
ULL ml = binpow(inv ? IGEN : GEN, LEN / len);
for (int i = 0; i < SZ(a); i += len)
{
ULL pw = 1;
FOR(j, 0, len / 2)
{
ULL v = a[i + j];
ULL u = mult(a[i + j + len / 2], pw);
a[i + j] = add(v, u);
a[i + j + len / 2] = sub(v, u);
pw = mult(pw, ml);
}
}
}
if (inv)
{
ULL m = binpow(SZ(a), mod - 2);
FOR(i, 0, SZ(a))
a[i] = mult(a[i], m);
}
}
VI mult(VI a, VI b)
{
vector<ULL> A(ALL(a)), B(ALL(b));
FOR(i, 0, SZ(a))
assert(a[i] >= 0 && a[i] < p);
FOR(i, 0, SZ(b))
assert(b[i] >= 0 && b[i] < p);
int sz = 0;
int sum = SZ(a) + SZ(b) - 1;
assert(sum <= 2 * p + 47);
while ((1 << sz) < sum)
sz++;
A.resize(1 << sz);
B.resize(1 << sz);
fft(A, false);
fft(B, false);
FOR(i, 0, SZ(A))
A[i] = mult(A[i], B[i]);
fft(A, true);
VI res(sum);
FOR(i, 0, sum)
{
res[i] = A[i] % p;
assert(res[i] >= 0);
}
return res;
}
int sub(int a, int b)
{
return a - b >= 0 ? a - b : a - b + p;
}
void updAdd(int& a, int b)
{
a += b;
if (a >= p)
a -= p;
}
void updSub(int& a, int b)
{
a -= b;
if (a < 0)
a += p;
}
int mult(int a, int b)
{
return (LL)a * b % p;
}
int binpow(int a, int n)
{
int res = 1;
while (n)
{
if (n & 1)
res = mult(res, a);
a = mult(a, a);
n /= 2;
}
return res;
}
VI inverse(const VI& a, int k)
{
assert(SZ(a) == k && a[0] != 0);
if (k == 1)
return {binpow(a[0], p - 2)};
VI ra = a;
FOR(i, 0, SZ(ra))
if (i & 1)
ra[i] = sub(0, ra[i]);
int nk = (k + 1) / 2;
VI t = mult(a, ra);
t.resize(k);
FOR(i, 0, nk)
t[i] = t[2 * i];
t.resize(nk);
t = inverse(t, nk);
t.resize(k);
RFOR(i, nk, 1)
{
t[2 * i] = t[i];
t[i] = 0;
}
VI res = mult(ra, t);
res.resize(k);
return res;
}
void removeLeadingZeros(VI& a)
{
while (SZ(a) > 0 && a.back() == 0)
a.pop_back();
}
pair<VI, VI> modulo(VI a, VI b)
{
removeLeadingZeros(a);
removeLeadingZeros(b);
if (a.empty())
{
return {{}, {}};
}
assert(SZ(a) != 0 && SZ(b) != 0);
int n = SZ(a), m = SZ(b);
if (m > n)
return MP(VI{}, a);
reverse(ALL(a));
reverse(ALL(b));
VI d = b;
d.resize(n - m + 1);
d = mult(a, inverse(d, n - m + 1));
d.resize(n - m + 1);
reverse(ALL(a));
reverse(ALL(b));
reverse(ALL(d));
VI res = mult(b, d);
res.resize(SZ(a));
FOR(i, 0, SZ(a))
res[i] = sub(a[i], res[i]);
removeLeadingZeros(d);
removeLeadingZeros(res);
return MP(d, res);
}
int x[LEN];
VI P[2 * LEN];
void build(int v, int tl, int tr)
{
if (tl + 1 == tr)
{
P[v] = {sub(0, x[tl]), 1};
return;
}
int tm = (tl + tr) / 2;
build(2 * v + 1, tl, tm);
build(2 * v + 2, tm, tr);
P[v] = mult(P[2 * v + 1], P[2 * v + 2]);
}
int Ans[LEN];
void solve(int v, int tl, int tr, const VI& q)
{
if (SZ(q) == 0)
return;
if (tl + 1 == tr)
{
Ans[tl] = q[0];
return;
}
int tm = (tl + tr) / 2;
solve(2 * v + 1, tl, tm,
modulo(q, P[2 * v + 1]).S);
solve(2 * v + 2, tm, tr,
modulo(q, P[2 * v + 2]).S);
}
complex<LL> mult(complex<LL> a, complex<LL> b)
{
a *= b;
a = {(a.real() % p + p) % p, (a.imag() % p + p) % p};
return a;
}
complex<LL> binpow(complex<LL> a, LL n)
{
complex<LL> res = {1, 0};
while (n)
{
if (n & 1)
res = mult(res, a);
a = mult(a, a);
n /= 2;
}
return res;
}
pair<VI, VI> splitRealImag(int k, const VI& a)
{
assert(SZ(a) == k + 1);
VI resReal(k + 1), resImag(k + 1);
FOR(i, 0, k + 1)
{
int r = (k - i) % 4;
if (r == 0)
{
updAdd(resReal[i], a[i]);
}
else if (r == 1)
{
updAdd(resImag[i], a[i]);
}
else if (r == 2)
{
updSub(resReal[i], a[i]);
}
else
{
updSub(resImag[i], a[i]);
}
}
return {resReal, resImag};
}
VI multipointEval(const VI& a, const VI& xs)
{
VI res;
for (int xi : xs)
{
int y = 0, Pw = 1;
for (int ai : a)
{
updAdd(y, mult(ai, Pw));
Pw = mult(Pw, xi);
}
res.PB(y);
}
return res;
}
vector<complex<LL>> f(int k)
{
FOR(i, 0, k)
x[i] = sub(0, i);
build(0, 0, k);
VI pol = P[0];
auto [polReal, polImag] = splitRealImag(k, pol);
FOR(i, 0, p)
x[i] = i;
build(0, 0, p);
solve(0, 0, p, modulo(polReal, P[0]).S);
VI ysReal(p);
FOR(i, 0, p)
ysReal[i] = Ans[i];
solve(0, 0, p, modulo(polImag, P[0]).S);
VI ysImag(p);
FOR(i, 0, p)
ysImag[i] = Ans[i];
vector<complex<LL>> res(p);
FOR(j, 0, p)
res[j] = {ysReal[j], ysImag[j]};
return res;
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
LL n;
cin >> p >> n;
vector<complex<LL>> f1 = f(p), f2 = f(n % p + 1);
complex<LL> ans = {1, 0};
FOR(j, 1, p)
ans = mult(ans, complex<LL>(0, j));
ans = binpow(ans, n / p);
FOR(j, 1, n % p + 1)
{
ans = mult(ans, complex<LL>(0, j));
}
ans = binpow(ans, n / p + 1);
FOR(xi, 1, p)
{
if (xi > n)
break;
ans = mult(ans, binpow(mult(binpow(f1[xi], n / p), f2[xi]), (n - xi) / p + 1));
}
cout << ans.real() << " " << ans.imag() << "\n";
return 0;
}
Details
Tip: Click on the bar to expand more detailed information
Test #1:
score: 100
Accepted
time: 2ms
memory: 5668kb
input:
2 1
output:
1 1
result:
ok single line: '1 1'
Test #2:
score: -100
Wrong Answer
time: 2ms
memory: 5632kb
input:
2 2
output:
0 0
result:
wrong answer 1st lines differ - expected: '1 1', found: '0 0'