YACS 2023年5月月赛 甲组 T1 子集和(六) 题解 您所在的位置:网站首页 慰问卡怎么做的图片 YACS 2023年5月月赛 甲组 T1 子集和(六) 题解

YACS 2023年5月月赛 甲组 T1 子集和(六) 题解

2023-05-29 20:05| 来源: 网络整理| 查看: 265

题目链接

YACS 老师说这是道分治,但就不告诉我怎么做,我硬是用线段树卡了过去...特别解气的是把 AC 图片发了过去(我就是在 YACS 上的编程课)

莫队

好了说点正经的,看到是谁谁谁的倍数就能想到 DP,状态设计也很水啦!设 $f[i]$ 为当前考虑到的区间内,子集和 $\% k = i$ 的数量。

新加入一个元素时,循环 0 ~ k - 1,更新 $f[i] = f[i - value] + f[i]$(value 是当前加的值,i - value 有可能为负,要取个模大家自己去弄)

这里还不能滚动数组,因为最前面的还会用到最后面的。

每次询问把 $f$ 清空,然后对参数 $l$ $r$ 做 DP 就可以做到 $O(qnk)$ 的复杂度,显然爆炸。

接着就开始了漫长的优化之旅。

首先让我想到的,是莫队,但是这个 dp 它不支持删除元素啊,所以还要搞不删除莫队,我懒了直接用在线莫队。

在线莫队我讲过,这里不废话,时间复杂度就是 $O(q\sqrt{n}\cdot k)$,然后循环展开了只能过 7 个点,看来是取模的问题。

#include #include using namespace std; //此题时间比较紧,所以要使用 fread 快读(读入正数) char buf[1 = k) l -= k; ret.f[l] = (ret.f[l] + x.f[i] * y.f[j] % mod) % mod; } } return ret; } void build (int l, int r, int k) { if (l == r) { for (int i = 0; i < k; i ++) a[k].f[i] = 0; ++ a[k].f[0]; ++ a[k].f[c[l] ]; return; } int mid = l + r >> 1; build (l, mid, k


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有