HDU 5106 Bits Problem (数位DP)

题目地址:HDU 5106

这个题要定义个dp结构体,dp[i][j].sum表示当前第i位还剩j个1的时候的和,dp[i][j].tot表示当前第i位还剩j个1的时候的符合要求的个数。不记录个数的话,当前位上的1无法跟着低位的出现而累加。

代码如下:

#include <iostream>
#include <string.h>
#include <math.h>
#include <queue>
#include <algorithm>
#include <stdlib.h>
#include <map>
#include <set>
#include <stdio.h>
using namespace std;
#define LL __int64
#define pi acos(-1.0)
const int mod=1e9+7;
const int INF=0x3f3f3f3f;
const double eqs=1e-9;
char c[1100];
LL d[1100];
int len;
struct node
{
        LL sum, tot;
}dp[1100][1100];
node dfs(int cnt, int one, int maxd, int zero)
{
        node tmp, ans;
        if(cnt==-1){
                tmp.tot=(!one&&maxd);
                tmp.sum=0;
                return tmp;
        }
        if(maxd&&zero&&dp[cnt][one].sum!=-1) return dp[cnt][one];
        int i, r=maxd?1:c[len-cnt-1]-'0';
        ans.sum=0;ans.tot=0;
        for(i=0;i<=r;i++){
                if(one-i>=0){
                        tmp=dfs(cnt-1,one-i,maxd||i<r,zero||i);
                        ans.sum+=(tmp.tot*d[cnt]*i+tmp.sum)%mod;
                        ans.tot=(ans.tot+tmp.tot)%mod;
                }
        }
        if(maxd&&zero){
                dp[cnt][one].sum=ans.sum;
                dp[cnt][one].tot=ans.tot;
        }
        return ans;
}
void init()
{
        int i, j;
        for(i=0;i<=1000;i++){
                for(j=0;j<=1000;j++){
                        dp[i][j].sum=-1;
                        dp[i][j].tot=0;
                }
        }
        d[0]=1;
        for(i=1;i<=1000;i++){
                d[i]=d[i-1]*2%mod;
        }
}
int main()
{
        int n, i, j;
        init();
        while(scanf("%d",&n)!=EOF){
                scanf("%s",c);
                len=strlen(c);
                node ans=dfs(len-1,n,0,0);
                printf("%I64d\n",ans.sum%mod);
        }
        return 0;
}
时间: 2024-08-14 22:12:39

HDU 5106 Bits Problem (数位DP)的相关文章

[数位dp] hdu 5106 Bits Problem

题意: 给一个N和一个R(用二进制表示) 问 [0,R)二进制中含有N个1的数之和 样例 1 1000 答案为 1+2+4=7 思路: 数位dp[1002][1002]第几位含有几个1 然后需要存的有两东西一个是有多少个数,以及和是多少 接着转移的时候 就是状态的sum=这个site的位权*之后含有的个数+之后的和 记得个数和和都要取模,一开始个数忘记取模了 %>_<% 然后需要优化  当当前1的个数已经超过sum了 直接返回0个数和是0 然后清空数组的时候只需要清空 1000*N个空间 (1

[ACM] hdu 2089 不要62(数位Dp)

不要62 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 19043    Accepted Submission(s): 6442 Problem Description 杭州人称那些傻乎乎粘嗒嗒的人为62(音:laoer). 杭州交通管理局经常会扩充一些的士车牌照,新近出来一个好消息,以后上牌照,不再含有不吉利的数字了,这样一来,就

HDU 2089 不要62(数位DP,三种姿势)

HDU 2089 不要62(数位DP,三种姿势) ACM 题目地址:HDU 2089 题意: 中文题意,不解释. 分析: 100w的数据,暴力打表能过 先初始化dp数组,表示前i位的三种情况,再进行推算 直接dfs,一遍搜一变记录,可能有不饥渴的全部算和饥渴的部分算情况,记录只能记录全部算(推荐看∑大的详细题解Orz) 代码: 1. 暴力 (以前写的) /* * Author: illuz <iilluzen[at]gmail.com> * File: 2089_bf.cpp * Create

HDU 4518 ac自动机+数位dp

吉哥系列故事--最终数 Time Limit: 500/200 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others) Total Submission(s): 304    Accepted Submission(s): 102 Problem Description 在2012年腾讯编程马拉松比赛中,吉哥解决了一道关于斐波那契的题目,这让他非常高兴,也更加燃起了它对数学特别是斐波那契数的热爱.现在,它又在思考一个关于斐波那契

hdu 3555 Bomb(数位dp)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3555 题目大意:就是给你一个数n,判断从0到n有多少个数含有数字49...... 是不是觉得跟hdu2089很相似呀... 思路:跟hdu2089一样的,注意给出的数比较大,所以这儿用__int64  .... code: #include<cstdio> #include<iostream> #include<cstring> #include<algorithm&

HDU - 3555 Bomb (数位DP)

题意:求1-n里有多少人包含"49"的数字 思路:数位DP,分三种情况:到第i位没有49的情况,到第i位没有49且最高位是9的情况,到第i位有49的情况,将三种情况都考虑进去就是了 #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; long long dp[30][3], n; int arr

HDU Word Index (数位DP)

题意:给你字符串,算出它的数值: a -> 1 b -> 2 . . z -> 26 ab -> 27 ac -> 28 . . az -> 51 bc -> 52 . . vwxyz -> 83681 字母要求递增. #include<cstdio> #include<stdlib.h> #include<string.h> #include<string> #include<map> #incl

HDU 4722 Good Numbers (数位dp)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4722 思路:数位dp,dp[i][j]表示到第i位,数字和%10为j,然后进行dp,注意完全匹配的情况是要+1,而其他情况是从0 到 9 都要考虑 代码: #include <stdio.h> #include <string.h> #include <algorithm> #include <iostream> using namespace std; int

hdu 5787 K-wolf Number 数位dp

数位DP 神模板 详解 为了方便自己参看,我把代码复制过来吧 // pos = 当前处理的位置(一般从高位到低位) // pre = 上一个位的数字(更高的那一位) // status = 要达到的状态,如果为1则可以认为找到了答案,到时候用来返回, // 给计数器+1. // limit = 是否受限,也即当前处理这位能否随便取值.如567,当前处理6这位, // 如果前面取的是4,则当前这位可以取0-9.如果前面取的5,那么当前 // 这位就不能随便取,不然会超出这个数的范围,所以如果前面取