Skip to main content
  1. Posts/

hdu 2089 不要62 (数位dp模板题,附带详细解释)

·2 mins
Note: This article is available in Chinese only. 本文暂无英文版本。 View original

题目链接 题意:问区间[n,m]中,不含数字4,也不含数字串“62”的所有数的个数。

思路:可以转化成求区间[0,x]

第一次接触数位dp,参考了这几篇博客。

不要62(数位dp)解题报告

解题报告2

解题报告3

比较重要的前提:

¨对于一个小于n的数,肯定是从高位到低位出现某一位<n的那一位。

¨如 n = 58 n为十进制数。

¨  x = 49 此时x的十位<n

¨  x = 51 此时x的个位<n

¨有了上述性质,我们就可以从高到低枚举第一次<n对应位是哪一位。

这样之前的位确定了,之后的位就不受n的限制即从00…0~99…9,可以先预处理

以及写成递归形式代码会简洁很多,所以就写了递归形式。

更详细的解释参加代码注释。

 1/* ***********************************************
 2Author :111qqz
 3Created Time :2016年03月15日 星期二 18时04分46秒
 4File Name :code/hdu/2089.cpp
 5************************************************ */
 6
 7#include <cstdio>
 8#include <cstring>
 9#include <iostream>
10#include <algorithm>
11#include <vector>
12#include <queue>
13#include <set>
14#include <map>
15#include <string>
16#include <cmath>
17#include <cstdlib>
18#include <ctime>
19#define fst first
20#define sec second
21#define lson l,m,rt<<1
22#define rson m+1,r,rt<<1|1
23#define ms(a,x) memset(a,x,sizeof(a))
24typedef long long LL;
25#define pi pair < int ,int >
26#define MP make_pair
27
28using namespace std;
29const double eps = 1E-8;
30const int dx4[4]={1,0,0,-1};
31const int dy4[4]={0,-1,1,0};
32const int inf = 0x3f3f3f3f;
33int n,m;
34int dp[30][2];
35int digit[30];
36
37int dfs (int pos,bool preis6,bool limit)  //pos表示从低到高的第几位,是从高位往低位递归的(也就是从左到又)
38					  // preis6 表示上一个数字是否为6,
39					  // limit表示该位置是否有限制。
40{
41//    cout<<pos<<" "<<preis6<<" "<<limit<<" "<<endl;
42    if (pos==0) return 1; //到该位置表明找到了一个解.
43
44    int res = 0 ;
45    if (!limit&&dp[pos][preis6]!=-1) return dp[pos][preis6];  //如果不是limit位置,表示结果是通用的,而之前又算过的话,就可以直接调用这个结果。
46    int mx = limit?digit[pos]:9; //mx第pos位置能取到的最大的数字..如果不是limit,则可以0..9任意取。
47//    cout<<"mx:"<<mx<<endl;
48
49    for ( int i = 0 ; i <= mx;  i++)
50    {
51	if (i==4||(i==2&&preis6)) continue;
52	res += dfs(pos-1,i==6,limit&&i==mx);
53	//(limit&&i==mx)中limit的含义是。。如果当前一位不是limit位(即0..9可以随便取的位置)
54	//,那么之后的位置也一定不是limit位置。
55	//而i==mx部分的意思是,在当前位置的数字小于当前位置的数字能取的最大值(mx)之前,
56	//后面位的数字随便取也不会超过上界。
57    }
58
59    if (!limit) dp[pos][preis6]=res;  //记忆化. 非limit位的结果才通用,不然没必要存。
60
61    return res;
62
63}
64int solve ( int n)
65{
66    ms(digit,0);  //将数按照每一位存到digit数组中
67    int len = 0 ;
68    while (n)
69    {
70	digit[++len] = n % 10;
71	n/=10;
72    }
73
74    return dfs(len,false,true);
75
76}
77
78int main()
79{
80	#ifndef  ONLINE_JUDGE
81	freopen("code/in.txt","r",stdin);
82  #endif
83
84	while (~scanf("%d %d",&n,&m))
85	{
86	    if (n==0&&m==0) break;
87
88	    ms(dp,-1);
89	    int ans = solve (m)-solve(n-1);
90
91	    printf("%d\n",ans);
92	}
93
94  #ifndef ONLINE_JUDGE
95  fclose(stdin);
96  #endif
97    return 0;
98}

Related

cf 611 B ||codeforces goodbye 2015 B. New Year and Old Property (数学或者数位dp)

http://codeforces.com/contest/611/problem/B 题意:问a到b(1E18),二进制表示中只有一个0的数有多少个。 思路:这么大的数。。。不是有循环节就是math problems. UD:20160318讲道理还有可能是数位dp好不好。。。 我们发现可以很容易得算出1到x的二进制表示中只有一个0 的数有多少个。

codeforces 148 D. Bag of mice

·2 mins
http://codeforces.com/problemset/problem/148/D # 题意:盒子里有w只白老鼠,b只黑老鼠,公主和魔王轮流取(公主先),先取到白老鼠的人获胜。魔王每次取完以后,盒子中的老鼠会因为吓尿了跑掉一只,跑掉的老鼠不算任何人取的。问公主获胜的概率。

codeforces 518 D. Ilya and Escalator

·1 min
http://codeforces.com/problemset/problem/518/D 题意:有n个人排队上一个电梯。。。在某一秒内,队首的人有p的概率上电梯,1-p的概率不动。每个人只有在队首的位置才可以上电梯(也就是每一秒内,最多只有一个人可以上电梯)。电梯无线长(也就是上了电梯就不会离开了),问在第t秒的时候,电梯上的人的个数的数学期望是多少。 # 思路:一开始推公式的我还是图样。这题是dp.其实也不难想。dp[i][j]表示第i秒时电梯上有j个人的概率。 当j==n的时候,也就是所以人都上了电梯以后。dp[i+1][j]+=dp[i][j],对于其他时刻 dp[i+1][j+1]+=dp[i][j]p,dp[i+1][j]+=dp[i][j](1-p). 初始化dp[0][0]=1,即0时刻电梯上有0个人的概率为1. # 1/* *********************************************** 2Author :111qqz 3Created Time :2016年02月02日 星期二 15时57分06秒 4File Name :code/cf/518D.cpp 5************************************************ */ 6 7#include <cstdio> 8#include <cstring> 9#include <iostream> 10#include <algorithm> 11#include <vector> 12#include <queue> 13#include <set> 14#include <map> 15#include <string> 16#include <cmath> 17#include <cstdlib> 18#include <ctime> 19#define fst first 20#define sec second 21#define lson l,m,rt<<1 22#define rson m+1,r,rt<<1|1 23#define ms(a,x) memset(a,x,sizeof(a)) 24typedef long long LL; 25#define pi pair < int ,int > 26#define MP make_pair 27 28using namespace std; 29const double eps = 1E-8; 30const int dx4[4]={1,0,0,-1}; 31const int dy4[4]={0,-1,1,0}; 32const int inf = 0x3f3f3f3f; 33const int N=2E3+7; 34int n,t; 35double p; 36double dp[N][N]; 37int main() 38{ 39 #ifndef ONLINE_JUDGE 40 freopen("code/in.txt","r",stdin); 41 #endif 42 ms(dp,0); 43 dp[0][0] = 1; 44 cin>>n>>p>>t; 45 for ( int i = 0 ; i <= t ; i++) 46 { 47 for ( int j = 0 ; j <= n ; j++) 48 { 49 if (j==n) 50 { 51 dp[i+1][j]+=dp[i][j]; 52 } 53 else 54 { 55 dp[i+1][j+1]+=dp[i][j]*p; 56 dp[i+1][j]+=dp[i][j]*(1-p); 57 } 58 } 59 } 60 double ans = 0 ; 61 for ( int j = 1 ; j <= n ; j++) 62 ans +=j*dp[t][j]; 63 64 printf("%.12f\n",ans); 65 66 #ifndef ONLINE_JUDGE 67 fclose(stdin); 68 #endif 69 return 0; 70}

codeforces 30 C. Shooting Gallery

·1 min
http://codeforces.com/contest/30/problem/C 题意:给出n个target在一个二维平面上。给出每个target的坐标,出现的时间,以及击中的概率。target出现之后就会瞬间消失,枪移动的单位速度为1,射击不需要时间。问能击中的target的最大期望是多少。