QOJ.ac

QOJ

IDProblemSubmitterResultTimeMemoryLanguageFile sizeSubmit timeJudge time
#480260#8761. 另一个计数问题HiraethsoulWA 0ms3512kbC++203.7kb2024-07-16 11:50:032024-07-16 11:50:05

Judging History

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

  • [2024-07-16 11:50:05]
  • 评测
  • 测评结果:WA
  • 用时:0ms
  • 内存:3512kb
  • [2024-07-16 11:50:03]
  • 提交

answer

#include <bits/stdc++.h>

#define int long long

const int p = 998244353;
const int inv2 = 499122177;
const int inv4 = 748683265;
const int inv6 = 166374059;

struct Min25 // 传入一个n  先求g函数 再求s函数
{
  int n, cur;
  int cnt = 0;
  std::vector<int> id1, id2, w;
  std::vector<int> g1, g2; // 两个前缀和
  std::vector<int> a, vis, s, t;
  int get_id(int val)
  {
    return (val <= cur ? id1[val] : id2[n / val]);
  } // 注意w要开2*cur的空间 因为整除分块最多有2*sqrt(n)种取值
  Min25(int n) : n(n), cur(sqrt(n)), w(2 * cur + 10), g1(2 * cur + 10), g2(2 * cur + 10), a(cur + 10), vis(cur + 10, 0), s(cur + 10), t(cur + 10), id1(cur + 10), id2(cur + 10)
  {
    s[0] = t[0] = 0;
    vis[0] = vis[1] = true;
    for (int i = 2; i <= cur; ++i)
    {
      if (!vis[i])
      {
        a[++cnt] = i;
        s[cnt] += (s[cnt - 1] + i * i % p) % p;
        t[cnt] += (t[cnt - 1] + i) % p;
      }
      for (int j = 1; j <= cnt and i * a[j] <= cur; ++j)
      {
        vis[i * a[j]] = true;
        if (i % a[j] == 0)
        {
          break;
        }
      }
    } // 欧拉筛预处理前缀和
    int tot = 0;
    for (int i = 1, j; i <= n; i = j + 1) // 整除分块预处理id和g(0,m)
    {
      j = n / (n / i);
      int val = n / i;
      w[++tot] = val;
      if (val <= cur)
      {
        id1[val] = tot;
      }
      else
      {
        id2[n / val] = tot;
      }
      val %= p;
      // 求g(0,m)实际上是前缀和但是要去掉1
      g1[tot] = (val * (val + 1) / 2 % p - 1 + p) % p;
      g2[tot] = ((val * (val + 1) % p * (2ll * val + 1) % p * inv6 % p) % p - 1 + p) % p;
    }

    for (int j = 1; j <= cnt; ++j) // dp出g[j][id]
    {
      for (int i = 1; i <= tot and a[j] * a[j] <= w[i]; ++i)
      {
        int k = get_id(w[i] / a[j]);
        g1[i] = (g1[i] - a[j] * (g1[k] - t[j - 1] + p) % p + p) % p;
        g2[i] = (g2[i] - a[j] * a[j] % p * (g2[k] - s[j - 1] + p) % p + p) % p;
      }
    }
  }
  int getprimepres1(int n) // 质数处的函数值的前缀和
  {
    int k = get_id(n);
    return g1[k];
  }
  int getprimepres2(int n) // 质数处的函数值的前缀和
  {
    int k = get_id(n);
    return g2[k];
  }
  int getS(int x, int y)
  {
    if (x < a[y] or x <= 1)
    {
      return 0;
    }
    int k = get_id(x);
    int res = ((g2[k] - g1[k] + p) % p - (s[y - 1] - t[y - 1] + p) % p + p) % p;
    for (int i = y; i <= cnt and a[i] * a[i] <= x; ++i)
    {
      int t1 = a[i], t2 = a[i] * a[i];
      for (int j = 1; t2 <= x; ++j, t1 = t2, t2 = t2 * a[i])
      {
        int tt1 = t1 % p, tt2 = t2 % p;
        res = (res + getS(x / t1, i + 1) * tt1 % p * (tt1 - 1) % p + tt2 * (tt2 - 1) % p) % p;
      }
    }
    return res;
  }
  int getpre(int n) // 前缀和
  {
    return (getS(n, 1) + 1) % p;
  }
};

signed main()
{
  std::ios::sync_with_stdio(0);
  std::cin.tie(0);
  int n;
  std::cin >> n;
  int cur = n % p;
  int ans = (((cur * cur % p * (cur + 1) % p * (cur - 2 + p) % p) * inv2 % p - ((cur * cur % p * (cur - 1 + p) % p * (cur - 1 + p) % p) * inv4 % p - 1 + p) % p) + cur * (cur + 1) % p * (cur - 2 + p) % p * inv2 % p - ((cur * (cur - 1 + p) % p * (2 * cur % p - 1 + p) % p) * inv6 % p - 1 + p) % p + 2 * p) % p;
  ans = ans * inv2 % p;
  cur = n / 2;
  Min25 calc(n);
  Min25 calc1(cur);
  int sum1 = calc.getprimepres1(n) - calc1.getprimepres1(cur); // 质数和
  int sum2 = calc.getprimepres2(n) - calc1.getprimepres2(cur); // 质数平方和
  std::cout << sum1 << ' ' << sum2 << '\n';

  int res = ((n * (n + 1) / 2 % p - 1 + p) % p * sum1 % p - sum2 - (sum1 * sum1 % p - sum2 + p) % p * inv2 % p % p + p) % p;

  ans = (ans - res + p) % p;
  std::cout << ans << '\n';
}

Details

Tip: Click on the bar to expand more detailed information

Test #1:

score: 0
Wrong Answer
time: 0ms
memory: 3512kb

input:

4

output:

3 9
8

result:

wrong answer 1st numbers differ - expected: '8', found: '3'