F - Hop Sugoroku
F - Hop Sugoroku
Problem Statement
There is a row of squares labeled and a sequence of length .
Initially, square is painted black, the other squares are painted white, and a piece is placed on square .
You may repeat the following operation any number of times, possibly zero:
- When the piece is on square , choose a positive integer and move the piece to square .
- Here, you cannot make a move with .
- Then, paint the square black.
Find the number of possible sets of squares that can be painted black at the end of the operations, modulo .
Constraints
- All input values are integers.
Input
The input is given from Standard Input in the following format:
Output
Print the answer as an integer.
Sample Input 1
5
1 2 3 1 1
Sample Output 1
8
There are eight possible sets of squares painted black:
- Square
- Squares
- Squares
- Squares
- Squares
- Squares
- Squares
- Squares
Sample Input 2
1
200000
Sample Output 2
1
Sample Input 3
40
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
Sample Output 3
721419738
Be sure to find the number modulo .
解题思路
dp 的部分还是很容易想到的。定义 表示在前 个元素中且第 个元素染成黑色的所有方案的数量。根据从第 个位置出发可到达的下标来进行状态转移,因此状态转移方程就是 。其中状态转移的计算量是 级别,如果每个 都很小,那么整个 dp 的时间复杂度就会变成 。因此只有当 比较大时,这种朴素转移的计算量才会比较小。
这时候就可以考虑用根号分治了,取 (大致 级别)。当 时直接朴素转移,那么这部分整体的时间复杂度大致是 。当 时就不能直接转移了,反过来考虑 能从哪些下标 转移过来,即满足 的下标 。如果 是确定的,那么就有 。因此用 来统计满足 的 的总和,当枚举到 时,遍历 ,把 累加到 中,表示可以从 且 的下标 转移到位置 。另外当 时,只需让 累加 即可。这部分整体的时间复杂度为 。
考虑两种情况,那么总的时间复杂度就是 ,其中根据基本不等式 ,当 和 相等即均取 时,等号成立,因此这里 大概取 。
AC 代码如下,时间复杂度为 :
#include <bits/stdc++.h>
using namespace std;
const int N = 2e5 + 10, M = 460, mod = 998244353;
int a[N];
int f[N];
int s[M][M];
int main() {
int n;
scanf("%d", &n);
for (int i = 1; i <= n; i++) {
scanf("%d", a + i);
}
f[1] = 1;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= 450; j++) {
f[i] = (f[i] + s[j][i % j]) % mod;
}
if (a[i] <= 450) {
s[a[i]][i % a[i]] = (s[a[i]][i % a[i]] + f[i]) % mod;
}
else {
for (int j = i + a[i]; j <= n; j += a[i]) {
f[j] = (f[j] + f[i]) % mod;
}
}
}
int ret = 0;
for (int i = 1; i <= n; i++) {
ret = (ret + f[i]) % mod;
}
printf("%d", ret);
return 0;
}
参考资料
Editorial - AtCoder Beginner Contest 335 (Sponsored by Mynavi):https://atcoder.jp/contests/abc335/editorial/9038
暴力美学——浅谈根号分治:https://www.luogu.com.cn/blog/Amateur-threshold/pu-li-mei-xue-qian-tan-gen-hao-fen-zhi
本文来自博客园,作者:onlyblues,转载请注明原文链接:https://www.cnblogs.com/onlyblues/p/17970725
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效
2023-01-17 D. Friendly Spiders
2023-01-17 C. Interesting Sequence