QOJ.ac

QOJ

IDProblemSubmitterResultTimeMemoryLanguageFile sizeSubmit timeJudge time
#93359#6179. 最大平方问题xzggzh1100 ✓1513ms10256kbC++174.4kb2023-03-31 17:53:322023-03-31 17:53:33

Judging History

你现在查看的是最新测评结果

  • [2023-08-10 23:21:45]
  • System Update: QOJ starts to keep a history of the judgings of all the submissions.
  • [2023-03-31 17:53:33]
  • 评测
  • 测评结果:100
  • 用时:1513ms
  • 内存:10256kb
  • [2023-03-31 17:53:32]
  • 提交

answer

//这回只花了45min就打完了。
//真好。记得多手造几组。最好有暴力对拍。 
#include<bits/stdc++.h>
using namespace std;

#define ll long long
const int N = 4e5 + 10, P = 998244353;
const ll kBuf = 27, kLim = 2.5e9, kMax = 1ll << kBuf;

ll a, b, c, n;
ll f[N], g[N], mx;

inline ll Mod(ll x, ll p) {
  return (x % p + p) % p;
}

inline ll Mul(ll x, ll y, ll p) {
  x = Mod(x, p), y = Mod(y, p);
  if (x < kLim && y < kLim) return x * y % p;
  ll l = x * (y >> kBuf) % p * kMax % p;
  ll r = x * (y & (kMax - 1)) % p;
  return (l + r) % p;
} //要保证x y均为正数 

ll ksm(ll x, ll t, ll p) {
  ll res = 1;
  while (t) {
    if (t & 1) res = Mul(res, x, p);
    x = Mul(x, x, p);
    t >>= 1;
  }
  return res;
} 

ll gcd(ll a, ll b) {
  while (b) {
    swap(a, b);
    b %= a; 
  }
  return a;
}

ll exgcd(ll a, ll b, ll &x, ll &y) {
  if (!b) {
    x = 1, y = 0;
    return a;
  }
  ll d = exgcd(b, a % b, x, y);
  ll tmp = x;
  x = y, y = tmp - a / b * y;
  return d; //debug 谢谢编译器 
}

struct Complex{
  ll rl, im;
  Complex(): rl(1), im(0) {}
  Complex(ll rl, ll im): rl(rl), im(im) {}
};

ll Ipow;

Complex Mul(Complex x, Complex y, ll p) {
  return (Complex){
    (Mul(x.rl, y.rl, p) + Mul(Mul(x.im, y.im, p), Ipow, p)) % p,
    (Mul(x.rl, y.im, p) + Mul(x.im, y.rl, p)) % p
  };
}

ll ksm(Complex x, ll t, ll p) {
  Complex res;
  while (t) {
    if (t & 1) res = Mul(res, x, p);
    x = Mul(x, x, p); 
    t >>= 1;
  }
  return res.rl;
}

bool Check(ll n, ll p) {
  return (ksm(n, (p - 1) >> 1, p) == 1);
}

bool Cipolla(ll n, ll p, ll &x) {
  n %= p;
  if (!n) {
    x = 0;
    return true;
  }
  if (!Check(n, p)) return false;
  ll a; //debug 要定义在这里 
  do{
    a = (ll)rand() * rand() % p;
    Ipow = (Mul(a, a, p) + p - n) % p;
    if (!Ipow) {
      x = a;
      return true;
    } //debug 不能判断!a 
  } while (Check(Ipow, p));
  x = ksm((Complex){a, 1}, (p + 1) >> 1, p);
  return true;
}

ll Divide(ll *f, ll s, ll step, ll sz, ll p) {
  ll res = 0;
  for (ll i = s; i <= sz; i += step) {
    while (f[i] % p == 0) {
      f[i] /= p;
      ++res;
    }
  }
  return res;
}

ll Work(ll p) {
  if (p == 2 || gcd(a, p) != 1) 
    return Divide(f, 1, 1, n, p);
  ll res = 0;
  ll tmp = (Mul(b % p, b % p, p) - Mul(a * 4, c, p) + p) % p, delta;
  ll inv = ksm(a * 2 % p, p - 2, p);
  if (!c) {
    delta = b % p;
  } else {
    if (!Cipolla(tmp, p, delta)) 
      return 0;
  }
  ll ax = Mul(Mod((Mod(-b, p) + delta), p), inv, p);
  ll bx = Mul(Mod((Mod(-b, p) - delta), p), inv, p);
  res += Divide(f, ax ? ax : p, p, n, p); //debug 如果为0就麻烦了 
  if (bx != ax) res += Divide(f, bx ? bx : p, p, n, p);
  return res;
}

ll GetSum(ll p) {
  return ksm(p, (Work(p) >> 1) << 1, P);
}

ll pri[N];
int cnt;
bool vis[N];

void GetPrimes() {
  mx = max(max((ll)pow(f[n], 1.0 / 3), (ll)sqrt(g[n * 2])), n);
  for (int i = 2; i <= mx; ++i) {
    if (!vis[i]) {
      pri[++cnt] = i;
    }
    for (int j = 1; j <= cnt && i * pri[j] <= mx; ++j) {
      vis[i * pri[j]] = true;
      if (i % pri[j] == 0)
        break;
    }
  }
}

ll SolveSmall() {
  ll res = 1;
  for (int i = 1; i <= cnt; ++i) {
    ll p = pri[i];
    res = res * GetSum(p) % P;
  }
  return res;
}

ll SolveLarge() {
  ll res = 1;
  int sz = n * 2;
  for (int i = 1; i <= cnt; ++i) {
    ll p = pri[i];
    ll x, y, c = Mod(p - b, p);
    ll d = exgcd(a, p, x, y);
    if (c % d) continue;
    x = Mul(x, c / d, p);
    ll lim = p / d;
    x = Mod(x, lim);
    Divide(g, x ? x : lim, lim, sz, p); 
  }
  sort(g + 1, g + sz + 1);
  for (int i = 1; i <= sz; ++i) {
    if ((i != 1 && g[i] == g[i - 1]) || g[i] == 1) continue; //debug g[i] == 1也要continue 
    res = res * GetSum(g[i]) % P;
  }
  return res;
}

ll SolveLast() {
  ll res = 1;
  for (int i = 1; i <= n; ++i) {
    ll tmp = (ll)sqrt(f[i]);
    if (tmp * tmp == f[i])
      res = Mul(res, f[i], P);
  }
  return res;
}

int main() {
//  freopen("square.in", "r", stdin);
//  freopen("square.out", "w", stdout);
  
  scanf("%lld%lld%lld%lld", &a, &b, &c, &n);
  for (int i = 1; i <= n; ++i)
    f[i] = a * i * i + b * i + c;
  for (int i = 1; i <= 2 * n; ++i)
    g[i] = a * i + b;
    
  GetPrimes(); //debug
  ll ans = SolveSmall() * SolveLarge() % P * SolveLast() % P;
  printf("%lld", ans);
  return 0;
}

Details

Tip: Click on the bar to expand more detailed information

Test #1:

score: 5
Accepted
time: 0ms
memory: 7820kb

input:

17 3 17 14

output:

123798013

result:

ok 1 number(s): "123798013"

Test #2:

score: 5
Accepted
time: 3ms
memory: 7964kb

input:

1 18 0 6

output:

2073600

result:

ok 1 number(s): "2073600"

Test #3:

score: 5
Accepted
time: 1ms
memory: 7684kb

input:

20 6 20 14

output:

315851899

result:

ok 1 number(s): "315851899"

Test #4:

score: 5
Accepted
time: 2ms
memory: 7940kb

input:

81 190 40 125

output:

924770602

result:

ok 1 number(s): "924770602"

Test #5:

score: 5
Accepted
time: 0ms
memory: 7840kb

input:

108 31 110 122

output:

319532761

result:

ok 1 number(s): "319532761"

Test #6:

score: 5
Accepted
time: 4ms
memory: 7736kb

input:

988 194 1412 934

output:

871618879

result:

ok 1 number(s): "871618879"

Test #7:

score: 5
Accepted
time: 9ms
memory: 7848kb

input:

1956 1305 92 1061

output:

681879967

result:

ok 1 number(s): "681879967"

Test #8:

score: 5
Accepted
time: 59ms
memory: 7892kb

input:

75955 165029 149078 5607

output:

739160804

result:

ok 1 number(s): "739160804"

Test #9:

score: 5
Accepted
time: 33ms
memory: 7864kb

input:

3223 4143 3383 4499

output:

139873119

result:

ok 1 number(s): "139873119"

Test #10:

score: 5
Accepted
time: 74ms
memory: 7856kb

input:

9257 3632 1736 9497

output:

158679485

result:

ok 1 number(s): "158679485"

Test #11:

score: 5
Accepted
time: 136ms
memory: 7776kb

input:

13657 8517 9780 16829

output:

499148359

result:

ok 1 number(s): "499148359"

Test #12:

score: 5
Accepted
time: 86ms
memory: 7780kb

input:

152794 105986 145639 8507

output:

432311896

result:

ok 1 number(s): "432311896"

Test #13:

score: 5
Accepted
time: 5ms
memory: 7904kb

input:

2209 13866 42748 227

output:

576767941

result:

ok 1 number(s): "576767941"

Test #14:

score: 5
Accepted
time: 21ms
memory: 7700kb

input:

14279 7290 25915 2265

output:

173729704

result:

ok 1 number(s): "173729704"

Test #15:

score: 5
Accepted
time: 220ms
memory: 7692kb

input:

24703 6569 26356 26534

output:

108700579

result:

ok 1 number(s): "108700579"

Test #16:

score: 5
Accepted
time: 158ms
memory: 7948kb

input:

187348 185285 76358 13718

output:

425402711

result:

ok 1 number(s): "425402711"

Test #17:

score: 5
Accepted
time: 150ms
memory: 7944kb

input:

189507 133399 143282 13930

output:

608644351

result:

ok 1 number(s): "608644351"

Test #18:

score: 5
Accepted
time: 1513ms
memory: 10256kb

input:

102698 162019 98595 137546

output:

388084925

result:

ok 1 number(s): "388084925"

Test #19:

score: 5
Accepted
time: 154ms
memory: 7964kb

input:

152381 90362 151048 15578

output:

413943175

result:

ok 1 number(s): "413943175"

Test #20:

score: 5
Accepted
time: 579ms
memory: 7840kb

input:

34402 49259 74598 64198

output:

733372582

result:

ok 1 number(s): "733372582"