CF1967C Fenwick Tree

news/2025/1/15 13:02:18/文章来源:https://www.cnblogs.com/luckyblock/p/18407536

树状数组,计数

非常好玩的题,考察对树状数组本质形态的理解。

Link:https://codeforces.com/contest/1967/problem/C

简述

对于数列 \(a\),定义数列 \(f(a)\) 为对数列 \(a\) 建立的树状数组。即有:

\[f(a)_k = \sum_{i = k - \operatorname{lowbit}(k) + 1}^k a_i \]

给定 \(T\) 组数据,每组数据给定长度为 \(n\) 的数列 \(b\),参数 \(k\)。请构造长度为 \(n\) 的数列 \(a\),使得数列 \(a\) 在模 998244353 意义下满足 \(b = f^k(a)\)
\(1\le T\le 10^4\)\(1\le n\le 2\cdot 10^5\)\(1\le k\le 10^9\)\(0\le b_i< 998244353\)
3S,256MB。

分析

树状数组本质上是二进制优化的前缀和,由题目给定的式子可以看出来,每个树状数组的位置 \(s_k\) 实际上是以 \(k\) 为右端点的,长度为 \(\operatorname{lowbit}(k)\) 的区间的和。

而本题对给定数组做了 \(k\) 次建立树状数组的操作,实际上即对所有树状数组区间做了 \(k\) 维二进制优化的前缀和。众所周知做高维前缀和时,每个位置对之后的位置的贡献的系数由下表所示,由组合意义易知位于 \((x, y)\) 的系数的值即 \({{x + y}\choose {y}}\)

\(a\) 1 1 1 1
\(f^1\) 1 2 3 4
\(f^2\) 1 3 6 10
\(f^3\) 1 4 10 20
\(f^4\) 1 5 15 35

记需要还原出来的数列为 \(a\),考虑对于每个位置 \(i\) 会对哪些位置 \(p\) 的高维前缀和 \(f^k(p)\) 有贡献。由建树状数组的过程可知,\(p\) 可以通过树状数组插入操作进行枚举,易知此类位置只有 \(O(\log_2 n)\) 数量级。

根据高维前缀和的式子,手玩下系数矩阵,发现若位置 \(p\) 是在树状数组插入操作时第 \(j(j\ge 0)\) 个被枚举到的位置,则 \(a_i\)\(f^k(p)\) 的贡献的系数即为:

\[{{k+j-1}\choose{j}} = \frac{(k+j-1)}{j}{{k+j-2}\choose{j-1}} \]

于是考虑顺序枚举所有位置并进行还原,还原第 \(i\) 个位置的值 \(a_i\) 后,考虑枚举它有贡献的位置并减去 \(a_i\) 的贡献即可。

总时间复杂度 \(O(n\log n)\) 级别,代码非常好写!

哎呦我草太优美啦树状数组!

代码

//
/*
By:Luckyblock
*/
#include <bits/stdc++.h>
#define LL long long
#define lowbit(x) ((x)&(-x))
const int kN = 2e5 + 10;
const LL p = 998244353;
//=============================================================
int n, k;
LL b[kN], a[kN], ans[kN], inv[kN];
//=============================================================
//=============================================================
int main() {//freopen("1.txt", "r", stdin);std::ios::sync_with_stdio(0), std::cin.tie(0);inv[1] = 1;for (int i = 2; i <= 2e5; ++ i) {inv[i] = 1ll * (p - p / i + p) % p * inv[p % i] % p;}int T; std::cin >> T;while (T --) {std::cin >> n >> k;for (int i = 1; i <= n; ++ i) std::cin >> b[i], a[i] = b[i];for (int i = 1; i <= n; ++ i) {ans[i] = a[i];LL c = 1, d = 0;for (int j = i; j <= n; j += lowbit(j)) {a[j] = (a[j] - c * ans[i] % p + p) % p;c = c * (k + d) % p * inv[d + 1] % p;++ d;}}for (int i = 1; i <= n; ++ i) std::cout << ans[i] << " ";std::cout << "\n";}return 0;
}
/*
打表看对位置 8 有贡献的位置的的系数矩阵的代码:int a[15][15][15] = {0};for (int i = 1; i <= 8; ++ i) a[0][i][i] = 1;for (int i = 1; i <= 10; ++ i) {for (int j = 1; j <= 8; ++ j) {if (j % 2 == 1) {a[i][j][j] = 1;continue;}if (j == 2 || j == 6) {a[i][j][j] = 1, a[i][j][j - 1] = i;}if (j == 4) {for (int k = j - 3; k <= j; ++ k) {for (int l = 1; l <= 8; ++ l) {a[i][j][l] += a[i - 1][k][l];}}}if (j == 8) {for (int k = j - 7; k <= j; ++ k) {for (int l = 1; l <= 8; ++ l) {a[i][j][l] += a[i - 1][k][l];}}}}std::cout << i << ": ";for (int j = 1; j <= 8; ++ j) printf("%5d", a[i][8][j]);std::cout << "\n";}
*/

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/795248.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

zliabary最新入口,zliabary国内官网镜像站网址(持续更新)

​zliabary是全球最大的电子书网站,从2009年开始提供免费的电子书,到如今已经拥有1000万多本书籍和8000万篇文章,是最大的影子图书馆,由于美国政府的屏蔽,zliabary已经从24年5月退出了国内市场,zliabary官网国内暂时登录不了。国内目前有两种可以使用zliabary方法,第一种…

软工第二次作业

软工作业2:个人项目-论文查重 GitHub链接: github 课程信息课程: 计科22级2班 - 广东工业大学 作业要求: 作业要求 目标: 完成个人项目-论文查重;学会写单元测试一、PSP表格PSP2.1 Personal Software Process Stages 预估耗时(分钟) 实际耗时(分钟)Planning 计划 60 30Es…

Pyqt5 实现多标签页面

实现功能代码实现 import sysfrom PyQt5.QtWidgets import QApplication, QMainWindow, QTabWidget, QVBoxLayout, QPushButton, QWidget, QLabel, \QDesktopWidgetclass MainWindow(QMainWindow):def __init__(self):super().__init__()self.ini_ui()def ini_ui(self):self.se…

gitee【下载文件】

1.配置公钥(如果是新设备) ssh-keygen -t ed25519 -C "Gitee SSH Key"输入这行命令,按3次回车,演示如下: 生成的公钥就在红框文件夹下复制该字符串,进入gitee的设置中,找到公钥粘贴该字符串配置完后可用该命令测试 ssh -T [git@gitee.com](mailto:git@gitee.c…

gitee【上传文件】

1.配置公钥 ssh-keygen -t ed25519 -C "Gitee SSH Key"输入这行命令,按3次回车,演示如下: 生成的公钥就在红框文件夹下复制该字符串,进入gitee的设置中,找到公钥粘贴该字符串配置完后可用该命令测试 ssh -T [git@gitee.com](mailto:git@gitee.com)2.新建仓库并配…

【技术积累】腾讯/阿里云对象存储上传+删除

腾讯/阿里云对象存储上传+删除创建储存桶 (后面会用到 储存库名称、访问域名、以及region) region(地域和访问域名)的查询参考: https://cloud.tencent.com/document/product/436/6224 https://www.aliyun.com/product/oss常用的阿里云、腾讯云2.创建Api密钥 (后面会用到…

虚拟机安装 gho系统

1.新建 虚拟机2.使用 _优先安装WePE_64_V2.3.exe 制作一个可启动iso3.gho文件 用UltraISO 制作为一个iso文件4.虚拟机用 前面制作的iso文件启动后 分区 ,然后启动 gho工具,再加载iso文件5.此时可以进行克隆还原了

Qt使用绿色pdf阅读器打开文件

1.下载SumatraPDF 2.设置 3.代码void MainWindow::on_pushButton_clicked() {QProcess *process = new QProcess();QString filePath = "C:\\Users\\jude\\Desktop\\su\\11.pdf";QString sumatraPath = "C:\\Users\\jude\\Desktop\\su\\SumatraPDF-3.5.2-64.exe…

基于tf-idf的论文查重

基于tf-idf的论文查重 github地址:https://github.com/gomevie/gomevie/tree/main这个作业属于哪个课程 广工计院计科34班软工这个作业要求在哪里 作业要求 这个作业的目标 设计并实现一个论文查重算法,通过比较原文和抄袭版论文文件,计算并输出重复率。PSP表格PSP2.1 Pers…

Java SE 语法学习

JavaSE 语法 java数据类型基本数据类型整数类型byte 占1个字节,范围:-128-127 short占2个字节,范围:-32768-32767 int占4个字节,范围:-2147483648-2147483647 long占8个字节,范围:-9223372036854775808-9223372036854775807浮点数类型double占8个字节 float占4个字节字…

今天学习和总结

学习了简单的算法知识排序中的快速排序,利用分治的思想来实现快速排序,对于前后大小有问题的进行swap的交换位置,这是基本的模版和源码 include using namespace std; define N 1000100 int A[N]; void quick_sort(int a,int b){ if(a>=b)return ; int i=a-1,j=b+1,x=A[a+b&…