您的位置:首页 > 其它

Hdu-5921 Binary Indexed Tree(数位DP)

2017-01-31 14:27 357 查看
[align=left]Problem Description[/align]
Recently, Mr. Frog has learned binary indexed tree. Here is the code of adding t to the interval [1,x]:
void add (int x, int t ){
for (int i = x; i != 0; i -= i & (-i))
a[i] += t;
}


If Mr. Frog is required to add t to the interval [l,r], he will add(r,t), and then add(l - 1,-t).

The cost of an interval [l,r] is defined as the number of the “really changed point”. The “really changed point” is the point whose value is modified by the given code.

For example, in order to add 1 to the interval [6,6], Mr. Frog will add 1 to the interval [1,6] (a[6] and a[4] will be added by 1), and add -1 to the interval [1,5] (a[5] and a[4] will be added by -1).

As the result, a[6] will be added by 1, a[5] will be added by -1, and a[4] will be added by 0. a[6] and a[5] are “really changed point”, and the cost is 2.

Mr. Frog wants to calculate the sum of the cost of the interval [l,r]⊆
[1,n] where l and r are two integers. Help Mr. Frog solve the problem.
 

[align=left]Input[/align]
The first line contains only one integer T (T≤10000),
which indicates the number of test cases.

For each test case, it contains an integer n (1≤n≤1018).
 

[align=left]Output[/align]
For each test case, output one line ”Case #x: y”, where x is the case number (starting from 1), y is the sum of the cost (modulo 1000000007).
 

[align=left]Sample Input[/align]

3
1
2
3

 

[align=left]Sample Output[/align]

Case #1: 1
Case #2: 4
Case #3: 10

 

[align=left]Source[/align]
2016中国大学生程序设计竞赛(长春)-重现赛

 

[align=left]Recommend[/align]
wange2014

题意略.

分析:我们把这棵树画出来,然后考虑分别计算树上每个节点对答案的贡献,很容易发现每个节点对答案的贡献为 子树个数*(n-子树个数+1),只和子树个数相关,所以我们只要分别计算出子树个数为2^k的树有多少个就行了,这个很容易用数位dp实现,但是这样直接统计计算的答案是不正确的,因为最大节点编号的限制那些编号特别大的子节点是不能算入答案的,所以我们把这种边界情况单独计算就可以了。

#include<iostream>
#include<string>
#include<algorithm>
#include<cstdlib>
#include<cstdio>
#include<set>
#include<map>
#include<vector>
#include<cstring>
#include<stack>
#include<queue>
#define INF 2147483640
#define eps 1e-9
#define MAXN 30010
#define MOD 1000000007
typedef long long ll;
using namespace std;
int t,pos,j,a[65];
ll n,dp[65][2];
ll dfs(int pos,int limit)
{
if(pos == j) return !limit;
if(dp[pos][limit] >= 0) return dp[pos][limit];
int up = limit ? a[pos] : 1;
ll ans = 0;
for(int i = 0;i <= up;i++)
{
ans += dfs(pos-1,limit && i == up);
if(ans >= MOD) ans %= MOD;
}
dp[pos][limit] = ans;
return ans;
}
void solve(ll x)
{
pos = 0;
while(x)
{
a[pos++] = x & 1;
x >>= 1;
}
}
int main()
{
scanf("%d",&t);
for(int T = 1;T <= t;T++)
{
scanf("%I64d",&n);
solve(n);
ll ans = 0;
for(j = 0;(1ll<<j) <= n;j++)
{
memset(dp,-1,sizeof(dp));
ans = (ans + ((dfs(pos-1,1)*((1ll<<j) % MOD) % MOD)*((n + 1 - (1ll<<j)) % MOD)) % MOD) % MOD;
if(a[j])
{
ll temp = (n - ((n>>j)<<j) + 1) % MOD;
ans = (ans + (temp*((n + 1 - temp) % MOD)) % MOD) % MOD;
}
}
printf("Case #%d: %I64d\n",T,ans);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: