二进制拆位计算贡献

题目描述

树状数组是一种常用的数据结构,下面是树状数组用于给区间 [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. Mac环境下制作ubantu安装盘

    前言:ubantu为Linux发行版之一,此方法亦可制作其他Linux发行版 1.在磁盘工具中将准备好的u盘格式化为Mac OS扩展(日志型),并确保分区的模式是GUID分区 2.官网自行下载uban ...

  2. 你必须学写 Python 装饰器的五个理由

    你必须学写Python装饰器的五个理由 ----装饰器能对你所写的代码产生极大的正面作用 作者:Aaron Maxwell,2016年5月5日 Python装饰器是很容易使用的.任何一个会写Pytho ...

  3. jQuery EasyUI/TopJUI基本的数字输入框(保留两位小数,带前缀后缀...)

    jQuery EasyUI/TopJUI基本的数字输入框(保留两位小数,带前缀后缀...) numberbox(数值输入框) HTML required:必填字段,默认为false:prompt:显示 ...

  4. maven 参考

    系列文章,通俗易懂,可以看看 http://www.cnblogs.com/AlanLee/category/918828.html

  5. 2016 CCPC-Final

    A.The Third Cup is Free #include <bits/stdc++.h> using namespace std; typedef long long ll; in ...

  6. 03.Jquery Mobile中的按钮

    一. 基础按钮 1.设置链接的data-role,使其变成按钮. <a href="index.html" data-role="button">L ...

  7. 2017 Multi-University Training Contest - Team 7 Just do it

    http://acm.hdu.edu.cn/showproblem.php?pid=6129 题意:一次操作就是i从1~n有 A[i]=A[i]^A[i-1]^A[i-2]...^A[1] 那么这样操 ...

  8. win7设置管理员权限

    1.在运行中输入:secpol.msc 2.修改设置权限设置 3.在账户中, 将administrator启用并设置密码 将其他用户取消管理原权限,设置为user权限

  9. PHP函数生成随机数

    通常情况下,当我们要生成一个随机字符串时,总是先创建一个字符池,然后用一个循环和mt_rand()或rand()生成php随机数,从字符池中随机选取字符,最后拼凑出需要的长度,代码如下: <?p ...

  10. Strut2 Action的生命周期

    一般而言,Action都是放在Spring容器中管理的,我会把属性设为prototype,这样,每一个请求,都会创建一个action对象. 今天碰到一个问题,当我用从一个jsp页面中输入一个属性,比如 ...