QOJ.ac
QOJ
ID | 题目 | 提交者 | 结果 | 用时 | 内存 | 语言 | 文件大小 | 提交时间 | 测评时间 |
---|---|---|---|---|---|---|---|---|---|
#480260 | #8761. 另一个计数问题 | Hiraethsoul | WA | 0ms | 3512kb | C++20 | 3.7kb | 2024-07-16 11:50:03 | 2024-07-16 11:50:05 |
Judging History
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';
}
详细
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'