二进制拆位计算贡献

题目描述

树状数组是一种常用的数据结构,下面是树状数组用于给区间 [1,x] 内的数加 t 的代码:

 void add(int x,int t){
for (int i=x;i;i-=(i&(-i))){
cnt[i]+=t;
}
}

当你要给 [l,r] 区间加 x 时,肯定是先给 [1,l−1] 加 −x,然后给 [1,r] 加 x

令 f(l,r) 为:在 cnt 数组一开始为 0 的情况下给区间[l,r]区间加1后,cnt 数组有多少位置不为0。

现在给定 n,求  \sum_{l=1}^{n} \sum_{r=1}^{n} f(l,r),对1e9+7取模

输入格式

第一行 T

T 行, 一个 n

输出格式

T 行答案

数据范围

1≤n≤10^18,1≤T≤10^4


题目分析

这题主流做法是数位dp。不过从hdu5921Binary Indexed Tree学习到一种拆位算贡献的方法

(但是请注意!上面引用的这篇博客关于f(i),g(i)的分析有写错的地方!)

本题树状数组求的是后缀和;而∑f(l,r)求的是l-1和r这两个数在依次减去lowbit的过程中不同的数的个数:那么只有当l-1和r变成lcp(l-1,r)时,接下去的数才会相同。

记g(i)为i二进制中1的个数,所求即

(公式崩了只能用图片)

经过上面分析之后,问题相当于转变为求∑g(i)和Σg(lcp(l-1,r))。由于数据范围是10^18级别,显然我们需要log算法。

将n二进制拆位,考虑从右往左第$i$位的贡献。记[i+1...lens]在十进制下为nxt[i+1],[1...i-1]在十进制下为pre[i-1]。

1.计算gi第一步:左边的数不改变

那么为了不大于原数,右边的数应取0...pre[i-1]。

当ai==1时,有pre[i-1]+1的贡献

2.计算gi第二步:左边的数可改变

与上一种情况相对应,左边的数应取0...nxt[i+1]-1.那么此时右边的数可以任意取值,有2^i种取值。

所以这种情况下,无论ai取值如何,都有nxt[i+1]*2^i的贡献。

至于还要处理两两lcp的部分,则与之类似。由于是数对之间的负贡献,算的时候再多乘上去就好了。

 #include<bits/stdc++.h>
typedef long long ll;
const ll MO = ; int T,bin[],lens;
ll n,ans,power[],pre[],nxt[]; ll read()
{
char ch = getchar();
ll num = ;
bool fl = ;
for (; !isdigit(ch); ch=getchar())
if (ch=='-') fl = ;
for (; isdigit(ch); ch=getchar())
num = (num<<)+(num<<)+ch-;
if (fl) num = -num;
return num;
}
int main()
{
T = read(), power[] = ;
for (int i=; i<=; i++) power[i] = (power[i-]<<)%MO;
while (T--)
{
n = read(), ans = lens = ;
for (ll x=n; x; x>>=) bin[++lens] = x&;
pre[] = nxt[lens+] = ;
for (int i=; i<=lens; i++) pre[i] = (pre[i-]+power[i-]*bin[i])%MO;
for (int i=lens; i>=; i--) nxt[i] = ((nxt[i+]<<)+bin[i])%MO;
for (int i=; i<=lens; i++)
{
if (bin[i]) pre[i-]++, ans = (ans+pre[i-])%MO;
ans = (ans+nxt[i+]*power[i-]%MO)%MO;
}
ans = (n+1ll)%MO*ans%MO;
for (int i=; i<=lens; i++)
{
if (bin[i]) ans = (ans+MO-pre[i-]*pre[i-]%MO)%MO;
ans = (ans-nxt[i+]*power[i-]%MO*power[i-]%MO+MO)%MO;
}
printf("%lld\n",ans);
}
return ;
}

END

【计数】hdu5921Binary Indexed Tree的更多相关文章

  1. Hdu5921 Binary Indexed Tree

    Hdu5921 Binary Indexed Tree 思路 计数问题,题目重点在于二进制下1的次数的统计,很多题解用了数位DP来辅助计算,定义g(i)表示i的二进制中1的个数, $ans = \su ...

  2. Binary Indexed Tree

    我借鉴了这个视频中的讲解的填坑法,我认为非常易于理解.有FQ能力和基本英语听力能力请直接去看视频,并不需要继续阅读. naive 算法 考虑一个这样的场景: 给定一个int数组, 我们想知道它的连续子 ...

  3. Leetcode: Range Sum Query 2D - Mutable && Summary: Binary Indexed Tree

    Given a 2D matrix matrix, find the sum of the elements inside the rectangle defined by its upper lef ...

  4. SRM 627 D1L2GraphInversionsDFS查找指定长度的所有路径 Binary indexed tree (BIT)

    题目:http://community.topcoder.com/stat?c=problem_statement&pm=13275&rd=16008 由于图中边数不多,选择DFS遍历 ...

  5. 树状数组(Binary Indexed Tree,BIT)

    树状数组(Binary Indexed Tree) 前面几篇文章我们分享的都是关于区间求和问题的几种解决方案,同时也介绍了线段树这样的数据结构,我们从中可以体会到合理解决方案带来的便利,对于大部分区间 ...

  6. Binary Indexed Tree (Fenwick Tree)

    Binary Indexed Tree 主要是为了存储数组前缀或或后缀和,以便计算任意一段的和.其优势在于可以常数时间处理更新(如果不需要更新直接用一个数组存储所有前缀/后缀和即可).空间复杂度O(n ...

  7. Binary Indexed Tree 总结

    特点 1. 针对 数组连续子序列累加和 问题(需要进行频繁的 update.sum 操作): 2. 并非是树型结构,只是逻辑上层次分明: 3. 可以通过 填坑法 来理解: 4. 中心思想:每一个整数都 ...

  8. 树状数组(Binary Indexed Tree)

    树状数组(Binary Indexed Tree,BIT) 是能够完成下述操作的数据结构. 给一个初始值全为 0 的数列 a1, a2, ..., an (1)给定 i,计算 a1+a2+...+ai ...

  9. LeetCode10 Indexed tree

    Binary Indexed Tree(Fenwick tree): 是一个查询和修改复杂度都为log(n)的数据结构.主要用于查询任意两位之间的所有元素之和,但是每次只能修改一个元素的值:经过简单修 ...

随机推荐

  1. try catch finally的执行顺序学习

    try catch finally的执行顺序学习   首先执行try,如果有异常执行catch,无论如何都会执行finally,当有return以后,函数就会把这个数据存储在某个位置,然后告诉主函数, ...

  2. CODING 告诉你硅谷的研发项目管理之道(5)

    CODING 已经通过前四期文章,让大家逐步了解了一些硅谷优秀的项目管理者是如何工作.如何维持团队高效运作的.在过去的十几年中,中国的互联网行业发展过于迅猛,导致很多管理人员都是赶鸭子上架,商场如战场 ...

  3. Linux上部署黑马旅游网Bug集锦

  4. 黑马学习Ajax 概念和基本使用

  5. Win7系统控制面板“设备和打印机”打不开解决办法

    Win7系统控制面板“设备和打印机”打不开解决办法, 打开时显示界面如下: 可能原因: 1.设备和打印机对应的驱动故障引起无法打开的问题 2.服务未开启 3.系统文件损坏 解决方法: 1.更新驱动.可 ...

  6. struts2.5+框架使用通配符与动态方法

    概述:struts2.5以后加强了安全性,下面就是安全配置引发的问题 通配符: 在学习struts框架时经常会使用到通配符调用方法,如下: <package name="usercru ...

  7. Django ORM 事务操作

    事务 把一些列的操作(步骤)当作一个事务 全部的步骤都成功才成功 经典例子:银行转账 代码实现: import os if name == 'main': os.environ.setdefault( ...

  8. System.Span, System.Memory,还有System.IO.Pipelines

    System.Span, System.Memory,还有System.IO.Pipelines 使用高性能Pipelines构建.NET通讯程序 .NET Standard支持一组新的API,Sys ...

  9. NET Core项目

    在IIS上部署你的ASP.NET Core项目   概述 与ASP.NET时代不同,ASP.NET Core不再是由IIS工作进程(w3wp.exe)托管,而是使用自托管Web服务器(Kestrel) ...

  10. SQLServer数据库表字段超长,找到超长字段脚本

    平时开发系统时偶尔会遇到数据超长导致往数据库中保存时出错. 使用下边的脚本可以方便的找出超长的字段. 1.通过正式表创建临时表,修改临时表中varchar.nvarchar的长度为max ); ); ...