Hdu-5921 Binary Indexed Tree(数位DP)

来源:互联网 发布:tomcat修改端口号 编辑:程序博客网 时间:2024/06/05 02:16

Problem Description
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.
 

Input
The first line contains only one integer T (T10000), which indicates the number of test cases.

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

Output
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).
 

Sample Input
3123
 

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

Source
2016中国大学生程序设计竞赛(长春)-重现赛
 

Recommend

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 1000000007typedef 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);    }}


0 0
原创粉丝点击