AT_agc003_e 题解
神仙题,我会把我自己思考的过程一步步写出来。
初看这题时感觉没什么思路,所以随便算了点东西。很容易发现如果对于一个
然后就是这道题的精髓所在了!很容易就可以发现
以下设
前面的循环节可以用 solve (cnt - 1, len[cnt] / len[cnt - 1]) 处理,但是后面多余的呢?
这时我们发现需要改变 solve 函数了,设 solve (x, y) 为处理前
转移首先要找到第一个
另外,注意下边界问题,如果
分析一下时间复杂度,
时间主要用在了
现在的 solve 函数就成了这样:
void solve (int x, int y) { if (x <= n) { d[1] += y; d[x + 1] -= y; return; } int t = lower_bound (len + 1, len + cnt + 1, x) - len - 1; f[t] += x / a[t] * y; solve (x % a[t], y); }
结束后,我们倒序循环一下。
此题的
这样,时间复杂度降到了
少量注释的代码:
#include <iostream> #include <algorithm> #define int long long using namespace std; int n, q, cnt; int a[100005], d[100005], f[100005]; void solve (int x, int y) {//求解前 x 个字符的贡献乘上 y if (x <= n) { d[1] += y; d[x + 1] -= y; return; } int t = lower_bound (a + 1, a + cnt + 1, x) - a - 1; f[t] += x / a[t] * y;//其实是前 a[t] 个字符乘上 x / a[t] 加上剩余的。 solve (x % a[t], y); } signed main () { int x, z; cin >> n >> q; if (q == 0) { for (int i = 1; i <= n; i ++) cout << 1 << "\n"; return 0; } z = n; a[++ cnt] = n; for (int i = 1; i <= q; i ++) { cin >> x; n = min (n, x); while (cnt != 0 && a[cnt] >= x) -- cnt; a[++ cnt] = x; } solve (x, 1); for (int i = cnt; i >= 2; i --) { f[i - 1] += a[i] / a[i - 1] * f[i]; solve (a[i] % a[i - 1], f[i]); } d[1] += f[1]; d[n + 1] -= f[1]; for (int i = 1; i <= n; i ++) { d[i] += d[i - 1]; cout << d[i] << "\n"; } for (int i = n + 1; i <= z; i ++) cout << 0 << "\n"; return 0; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· C#/.NET/.NET Core技术前沿周刊 | 第 29 期(2025年3.1-3.9)
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异