UVA 12670 数位DP

来源:互联网 发布:日本留学融入 知乎 编辑:程序博客网 时间:2024/06/05 18:07

UVA 12670
题目链接:
https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=4536
题意:
给一个数字范围[x,y],问在这个范围内所有数表示成二进制后,“1”的个数和。
思路:
简单的数位DP,用那种BIT的思想去理解就好。
源码:

#include <cstdio>#include <cstring>#include <cmath>#include <cstdlib>#include <algorithm>#include <iostream>#include <string>using namespace std;#define LL long longconst int MAXN = 70;LL dp[MAXN];LL C[MAXN];LL cal(LL a){    string str = "";    while(a){        str += a % 2 + '0';        a /= 2;    }    LL ans = 0;//    cout << " str = " << str<<endl;//    str.reverse();    int len = str.length();    int cnt = 0;    for(int i = len - 1 ; i >= 0 ; i--){        if(str[i] == '1'){//            printf("i = %d, dp[i] = %lld\n", i, dp[i]);            ans += dp[i] + cnt * C[i];            cnt++;        }    }    ans += cnt;    return ans;}void init(){    dp[0] = 0;    C[0] = 1;    for(int i = 1 ; i < MAXN ; i++){        dp[i] = dp[i - 1] * 2 + C[i - 1];        C[i] = C[i - 1] * 2;    }}int main(){    init();    LL a, b;    while(scanf("%lld%lld", &a, &b) != EOF){        LL ans = cal(b) - cal(a - 1);//        printf("cal1 = %lld, cal2 = %lld\n", cal(b), cal(a - 1));        printf("%lld\n", ans);    }    return 0;}
0 0
原创粉丝点击