首页 > 其他分享 >CF1967C. Fenwick Tree-算子展开,树状数组的结构

CF1967C. Fenwick Tree-算子展开,树状数组的结构

时间:2024-05-05 23:34:22浏览次数:11  
标签:inv CF1967C lowbit Fenwick Tree ret int ll MOD

link:https://codeforces.com/problemset/problem/1967/C
题意:定义 \(f(a)=s\) 中的 \(f\) 表示把序列 \(a\) 映射为其树状数组的操作(\(s\) 就是对应的树状数组),并且操作是在取模下作的,已知 \(f^k (a)=b\),已知序列 \(b\) 和自然数 \(k\),求 \(a\).

\(1\leq n\leq 2\times 10^5,1\leq k\leq 10^9\).


\(f^k(a)=b\),把 \(f\) 看成一个序列的映射,\(f\) 的逆运算 \(f^{-1}\)能够表示出来:

例如原本

\[\begin{aligned} s_1&=a_1\\ s_2&=a_1+a_2\\ s_3&=a_3\\ s_4&=a_1+a_2+a_3+a_4\\ s_5&=a_5\\ s_6&=a_5+a_6 \end{aligned}\]

则逆运算相当于要求我们反过来用 \(s\) 求 \(a\):

\[\begin{aligned} a_1&=s_1\\ a_2&=s_2-s_1\\ a_3&=s_3\\ a_4&=s_4-s_3-(s_2-s_1)-s_1=s_4-s_3-s_2\\ a_5&=s_5\\ a_6&=s_6-s_5 \end{aligned}\]

根据我们平常写树状数组的习惯也可以看得出,一次逆运算就是反过来,把每个数 \(a_i\) 加到 \(s_i\),同时把 \(-a_i\) 加到 \(s[i+lowbit(i)]\) 的位置。

所以可以把 \(f^{-1}\) 拆开看,\(a_i\) 加到 \(s_i\) 是单位映射\(I\)(把a序列原封不动地映射成a序列),后面的操作用一个符号 \(A\) 表示把\(a_i\) 加到 \(s[i+lowbit(i)]\) 上,整个\(f^{-1}=I-A\).

要求 $$a=f^{-k} b=(I-A)^k b=\Big[\sum_{i=0}^k \binom{k}{i}(-1)^i A^i \Big] (b)$$
其中 \(A\) 表示上述运算, \(A^i\) 表示运算复合 \(i\) 次,比如 \(A^2\) 作用在 \(b_i\) 上,就表示将其加到 \(s[i+lowbit(i)+lowbit(i+lowbit(i))]\) 上,也就是在Fenwick Tree上跳两步的事情。很明显跳lowbit的过程至多 \(O(\log n)\) 步就会停止,因此和式中的 \(i\) 只需要处理大约20项左右,总的时间复杂度就是 \(O(n\log n)\)的。

代码很简单:

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define endl '\n'
#define fastio ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0)
using namespace std;
typedef long long ll;
const int N=2e5+5;
const int MOD=998244353;
int ksm(int a,int b){
    int ret=1;
    for(;b;b>>=1,a=(ll)a*a%MOD)if(b&1)ret=(ll)ret*a%MOD;
    return ret;
}
int n,k,b[N],ans[N];
int inv_fact[100];
int C(int n,int k){
    if(k>n)return 0;
    int ret=1;
    for(int i=n;i>=n-k+1;i--)ret=(ll)ret*i%MOD;
    return (ll)ret*inv_fact[k]%MOD;
}
int lowbit(int x){return x&-x;}
int main(){
    fastio;
    inv_fact[0]=1;
    rep(i,1,50)inv_fact[i]=(ll)inv_fact[i-1]*ksm(i,MOD-2)%MOD;
    int tc;cin>>tc;
    while(tc--){
        cin>>n>>k;
        rep(i,1,n)ans[i]=0;
        rep(i,1,n){
            cin>>b[i];
            for(int t=0,j=i;j<=n;j+=lowbit(j),t++){
                if(t&1)ans[j]=(ans[j]+MOD-(ll)C(k,t)*b[i]%MOD)%MOD;
                else ans[j]=(ans[j]+(ll)C(k,t)*b[i])%MOD;
            }
        }
        rep(i,1,n)cout<<ans[i]<<' ';
        cout<<endl;
    }
    return 0;
}

标签:inv,CF1967C,lowbit,Fenwick,Tree,ret,int,ll,MOD
From: https://www.cnblogs.com/yoshinow2001/p/18174083

相关文章

  • grid 与 treelist 的区别
    TreeList与Grid的主要区别体现在数据结构、展示方式和应用场景上。以下是具体的分析:数据结构:TreeList:TreeList是一种树状的数据结构,它可以理解为是一个有序、可重复的树状列表。这种数据结构不仅实现了List接口,还融入了树的特性,如父子节点的关系,这使得它在处理具有层级关系的......
  • devexpress中 cxTreeList 与 cxVirtualTreeList 区别
    在DevExpress控件库中,cxTreeList和cxVirtualTreeList都是用于展示层级数据的控件,但它们在使用场景、性能优化和数据加载方式等方面有所不同。以下是两者之间的主要区别:数据展示与交互:cxTreeList:提供了一个传统的树形列表视图,用户可以直观地看到数据的层级结构,并通过展开和折......
  • BinaryTree_CountLeafNode
    /*******************************************************************************************************@filename: :StacksSimulateQueue*@brief :两个栈实现队列的功能*@author :[email protected]*@date :2024/05/04*@version......
  • Codeforces 1129E Legendary Tree
    考虑让选取的集合更加特殊,不妨就让\(S=\{x\}\)。那么这个时候能发现询问\((S=\{x\},T,v)\)得到的就是以\(x\)为根时\(v\)的子树内\(T\)中的点的数量。考虑定个根,不妨为\(1\),同时令\(S=\{1\}\)。那么询问\((\{1\},\{1,\cdotsn\}\backslash\{1,x\},x)......
  • CompareBinaryTreeDepth
    /*******************************************************************************************************@filename: :CompareBinaryTreeDepth*@brief :采用递归的方式来计算二叉树的深度*@author :[email protected]*@date :2024/05/03*......
  • WPF TreeView HierarchicalDataTemplate
    //xaml<Windowx:Class="WpfApp87.MainWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:d="http://schemas.mic......
  • 「CF1017G」The Tree
    这是一道非常NB的题意转化题.Introduction给定一棵树,维护以下3个操作:1x表示如果节点\(x\)为白色,则将其染黑.否则对这个节点的所有儿子递归进行相同操作;2x表示将以节点\(x\)为\(root\)的子树染白;3x表示查询节点\(x\)的颜色.StrikingIdeas修改复......
  • CF1951I Growing Trees
    MyBlogsCF1951IGrowingTrees首先考虑确定了\(x_i\)如何判定是否合法。可以很容易的找出这样一个必要条件:\(\foralli,x_i\leqk\)。这是两个点的情况,考虑点数更多的情况。手玩之后可以推广到:对于任意导出子图,要求其内部的边数\(\leqk(|S|-1)\)。这个条件也是充分的,证明......
  • 树(tree) [一]
    树(tree)[一]基本概念:​ 日常生活中,很多数据的组织形式本质上是一棵树。比如一个公司中的职员层级关系、一个学校中的院系层级关系、淘汰赛中的各次比赛队伍、一个家族中的族谱成员关系等都是树状逻辑结构。由于树状结构表现出来都是具有层次的,因此也被称为层次结构。树是一种......
  • JDK源码分析-TreeSet
    概述TreeSet是Java集合框架中用于存储唯一元素的树形数据结构,它实现了NavigableSet接口,这意味着TreeSet中的元素不仅是有序的,还支持一系列的导航方法。TreeSet的内部实现主要依赖于TreeMap,通过TreeMap的键来维护元素的排序。 类图从以上类图可以看到,TreeSet实现了三个接口,......