POJ

来源:互联网 发布:网络热点新闻定义 编辑:程序博客网 时间:2024/06/01 10:51

题目链接:http://poj.org/problem?id=3252

感谢ECNU_LZJ的博客带来的思路   http://m.blog.csdn.net/ECNU_LZJ/article/details/74330589

数位DP  思路出来了  就直接套模板  不懂模板的可以来这学学http://www.cnblogs.com/zbtrs/p/6106783.html

定义状态dp[pos][one][zero][lead],pos为当前数位, one为前缀中1的个数 , zero为前缀中0的个数, lead,表示当前数位的前缀中有没有1。
注意前导0!假如要计算小于等于12的Round Number个数,12的长度为4,在dfs到3的时候,路径上的数字依次为0011,0的个数大于1的个数,所以3是符合条件的。真的对吗?
实际上前两个0都是前导0,去掉前导0之后,就发现3其实是不合法的了。
所以dfs的时候,维护一个变量lead,表示当前数位的前缀中有没有1。

/**定义状态dp[pos][one][zero][lead],pos为当前数位, one为前缀中1的个数 , zero为前缀中0的个数, lead,表示当前数位的前缀中有没有1。注意前导0!假如要计算小于等于12的Round Number个数,12的长度为4,在dfs到3的时候,路径上的数字依次为0011,0的个数大于1的个数,所以3是符合条件的。真的对吗?实际上前两个0都是前导0,去掉前导0之后,就发现3其实是不合法的了。所以dfs的时候,维护一个变量lead,表示当前数位的前缀中有没有1。*/#include <algorithm>#include <iostream>#include <cstring>#include <cstdlib>#include <cstdio>#define LL long long#define MEM(a, b) memset(a, b, sizeof(a))using namespace std;LL dp[35][35][35][3];LL l, r;int shu[35];LL dfs(int len, int one, int zero, int lead, bool shangxian){    if(zero + len < one) return 0;  //剪枝    if (len == 0)        return zero >= one; //当每位数字都枚举完(即len=0),并且zero >= one的时候才是有效的    if (!shangxian && dp[len][one][zero][lead] != -1)        return dp[len][one][zero][lead];  //dp数组的内容应和dfs调用参数的内容相同,除了是否达到上限    LL cnt = 0;    int maxx = (shangxian ? shu[len] : 1);    for (int i = 0; i <= maxx; i++)    {        if(i == 0)        {            if(lead)  //前缀有1时   当前位的0才有效                cnt += dfs(len - 1, one, zero + 1, lead, shangxian && i == maxx);            else                cnt += dfs(len - 1, one, zero, lead, shangxian && i == maxx);        }        else if(i == 1)            cnt += dfs(len - 1, one + 1, zero, 1, shangxian && i == maxx);    }    if (!shangxian)        dp[len][one][zero][lead] = cnt;    return cnt;}LL solve(LL x){    int k = 0;    while (x)    {        shu[++k] = x % 2;        x /= 2;    }    return dfs(k, 0, 0, 0, 1);}int main(){    memset(dp, -1, sizeof(dp));    while(scanf("%I64d %I64d", &l, &r) != EOF)    {        printf("%I64d\n", solve(r) - solve(l - 1));    }    return 0;}


原创粉丝点击