【Dream Counting, 2006 Dec-数数的梦】数位dp

题意:给定两个数,问区间[A,B]中0~9分别出现了多少次。A,B<=10^18

题解:应该是最裸的数位dp吧。。一开始没有记忆化tle了TAT

我们可以求出区间[0,B]的,再减去区间[0,A]的。

用dfs实现,记录flag(填了的位是否和边界重合),zero(当前是否还在前缀0中)

 1 #include<cstdio>
 2 #include<cstdlib>
 3 #include<cstring>
 4 #include<iostream>
 5 #include<ctime>
 6 #include<queue>
 7 using namespace std;
 8
 9 typedef long long LL;
10 const int N=100;
11 int c[N][N][2][2],d[N],sum[N];
12 LL bit[N],ret[N];
13
14 LL g(int now,int x,int flag,int zero)
15 {
16     if(c[now][x][flag][zero]!=-1) return c[now][x][flag][zero];
17     if(x==0) return 0;
18     LL ans=0;
19     if(flag)
20     {
21         for(int i=0;i<d[x];i++)
22         {
23             ans+=g(now,x-1,0,zero & (i==0));
24             if(i==now && !(i==0 && zero)) ans+=bit[x-1];
25         }
26         ans+=g(now,x-1,1,zero && (d[x]==0));
27         if(now==d[x] && !(now==0 && zero)) ans+=ret[x-1];
28     }
29     else
30     {
31         for(int i=0;i<=9;i++)
32         {
33             ans+=g(now,x-1,0,zero & (i==0));
34             if(i==now && !(i==0 && zero)) ans+=bit[x-1];
35         }
36     }
37     // printf("now %d  x %d  flag %d  zero %d  = %d\n",now,x,flag,zero,ans);
38     c[now][x][flag][zero]=ans;
39     return ans;
40 }
41
42 void solve(LL x,LL tmp)
43 {
44     memset(d,0,sizeof(d));
45     memset(c,-1,sizeof(c));
46     int l=0;LL y=x;
47     while(y)
48     {
49         d[++l]=(int)(y%10);
50         y/=10;
51     }
52     for(int i=0;i<=18;i++) ret[i]=x%bit[i]+1;
53     for(int i=0;i<=9;i++) sum[i]+=g(i,20,1,1)*tmp;
54 }
55
56 int main()
57 {
58     // freopen("a.in","r",stdin);
59     freopen("dream.in","r",stdin);
60     freopen("dream.out","w",stdout);
61     LL A,B;int x;
62     scanf("%lld%lld",&A,&B);
63     memset(sum,0,sizeof(sum));
64     bit[0]=1;
65     for(int i=1;i<=18;i++) bit[i]=bit[i-1]*10;
66     solve(A-1,-1);
67     solve(B,1);
68     for(int i=0;i<=9;i++) printf("%d ",sum[i]);
69     return 0;
70 }
时间: 2024-10-29 07:38:10

【Dream Counting, 2006 Dec-数数的梦】数位dp的相关文章

poj3208 Apocalypse Someday 数位dp+二分 求第K(K &lt;= 5*107)个有连续3个6的数。

/** 题目:poj3208 Apocalypse Someday 链接:http://poj.org/problem?id=3208 题意:求第K(K <= 5*107)个有连续3个6的数. 思路:数位dp+二分. dp[i][j]表示长度为i,前缀状态为j时含有的个数. j=0表示含有前导0: j=1表示前缀连续1个6 j=2表示前缀连续2个6 j=3表示前缀连续3个6 j=4表示前缀不是6: */ //#include<bits/stdc++.h> #include<cstr

uestc 250 windy数(数位dp)

题意:不含前导零且相邻两个数字之差至少为2的正整数被称为windy数. windy想知道,在A和B之间,包括A和B,总共有多少个windy数? 思路:数位dp #include<iostream> #include<stdio.h> #include<string.h> #include<algorithm> using namespace std; int dp[15][10];//dp[i][j]表示长度为i,最高位为j的windy数的个数 void i

BZOJ_1026_[SCOI2009]windy数_数位DP

题意:windy定义了一种windy数.不含前导零且相邻两个数字之差至少为2的正整数被称为windy数. windy想知道, 在A和B之间,包括A和B,总共有多少个windy数? 学一下数位DP. f[i][j]表示i位数以j开头的windy数个数.转移有f[i+1][k]+=f[i][j](abs(j-k)>=2) 答案转成[1~R]-[1~L-1]之后按位枚举,每次枚举到当前位上的数减1. 注意: 1.枚举到两位差2以内时停止枚举. 2.答案要加上位数比他小的所有windy数. 代码: 1

bzoj1026: [SCOI2009]windy数 数位dp

题目: http://www.lydsy.com/JudgeOnline/problem.php?id=1026 题意: Description windy定义了一种windy数.不含前导零且相邻两个数字之差至少为2的正整数被称为windy数. windy想知道, 在A和B之间,包括A和B,总共有多少个windy数? Input 包含两个整数,A B. Output 一个整数 思路: 数位dp,记忆化搜索. 1 #include <bits/stdc++.h> 2 3 using namesp

windy数(简单数位DP)

1026: [SCOI2009]windy数 Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 6306  Solved: 2810[Submit][Status][Discuss] Description windy定义了一种windy数.不含前导零且相邻两个数字之差至少为2的正整数被称为windy数. windy想知道,在A和B之间,包括A和B,总共有多少个windy数? Input 包含两个整数,A B. Output 一个整数 Sample I

BZOJ_1026_[SCOI2009]_windy数_(数位dp)

描述 http://www.lydsy.com/JudgeOnline/problem.php?id=1026 windy定义了一种windy数.不含前导零且相邻两个数字之差至少为2的正整数被称为windy数. windy想知道, 在A和B之间,包括A和B,总共有多少个windy数? 分析 我们用\(dp[i][j]\)表示以\(j\)开头的\(i\)为数中windy数一共有多少. 然后用\(solve(x)\)求出\([1,x]\)内的windy数一共有多少,步骤如下: 1.将\(x\)一位一

bin巨的数(数位DP)

题目描述 作为ACM史上年度重量级人物,bin巨目前已经掌握了史上最NB的数,群巨快来仰慕!!我们定义这样一个数,它里面的每一个数字都是成双成对出现 的,but,如果这个数里面存在0那么这也是NB的数,比如11,122122,12035,当然,需要剔除那些首位是0的数.我们的目标就是计算一个区 间内bin巨有多少NB数! 输入 输入第一行包含一个整数T,表示接下来有T组数据. 下面T行,每行包含两个数l和r,表示这个区间. 数据范围:0<=l<=r<=10^18 输出 输出T行,每行一个

hdu3652 数位dp(含13且被能被13整除的数)

http://acm.hdu.edu.cn/showproblem.php?pid=3652 B-number Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2815    Accepted Submission(s): 1552 Problem Description A wqb-number, or B-number for sh

BZOJ 1662: [Usaco2006 Nov]Round Numbers 圆环数(数位DP+恶心细节)

BZOJ 1662: [Usaco2006 Nov]Round Numbers 圆环数 Time Limit: 5 Sec  Memory Limit: 64 MB Description 正如你所知,奶牛们没有手指以至于不能玩“石头剪刀布”来任意地决定例如谁先挤奶的顺序.她们甚至也不能通过仍硬币的方式. 所以她们通过"round number"竞赛的方式.第一头牛选取一个整数,小于20亿.第二头牛也这样选取一个整数.如果这两个数都是 "round numbers"