hdu 5898 odd-even number 数位DP

odd-even number

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 716    Accepted Submission(s): 385

Problem Description

For a number,if the length of continuous odd digits is even and the length of continuous even digits is odd,we call it odd-even number.Now we want to know the amount of odd-even number between L,R(1<=L<=R<= 9*10^18).

Input

First line a t,then t cases.every line contains two integers L and R.

Output

Print the output for each case on one line in the format as shown below.

Sample Input

2
1 100
110 220

Sample Output

Case #1: 29

Case #2: 36

思路:数位DP的递归出口为pos = 0,这时只能判断DP状态末尾的情况,即对于构造一个数来说只能判断最低的奇偶相同的几位,那么如何才能知道中间是否有不符合的情况?

这就需要设置两个变量,一个表示第pos的奇偶性,一个表示以pos位为末尾的中间状态的长度。不过还在中间加上了一个前导0的标识zero.这个只为编码的方便,其实可以特判出是否为前导0的;

ps:说到底还是套路题....

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<algorithm>
  4 #include<queue>
  5 #include<set>
  6 #include<vector>
  7 #include<map>
  8 #include<cstring>
  9 #include<string>
 10 #include<cmath>
 11 using namespace std;
 12 #define MS1(a) memset(a, -1, sizeof(a))
 13 #define MS0(a) memset(a, 0,sizeof(a))
 14 #define rep1(i,a,b) for(int i = a; i <= b; i++)
 15 #define rep0(i,a,b) for(int i = a; i < b; i++)
 16 #define rep_0(i,a,b) for(int i = b; i > a; i--)
 17 #define rep_1(i,a,b) for(int i = b; i >= a; i--)
 18 #define inf 0x3f3f3f3f
 19 #define INF 0x3f3f3f3f3f3f3f3f
 20 #define bit(p) (1<<p)
 21 #define bitnum(a) __builtin_popcount(a)
 22 #define lowbit(x) (x&(-x))
 23 #define eps 1e-8
 24 #define mod 1000000007
 25 typedef pair<int,int> PII;
 26 #define ll long long
 27 #define ull unsigned long long
 28 #define uint unsigned int
 29 #define lson l, m, rt << 1
 30 #define rson m+1, r, rt << 1|1
 31 #define MK make_pair
 32 #define A first
 33 #define B second
 34 #define pb(a) push_back(a)
 35 #define zero(x) (((x)>0?(x):-(x))<eps)
 36 template<typename T>
 37 void read1(T &m)
 38 {
 39     T x = 0,f = 1;char ch = getchar();
 40     while(ch <‘0‘ || ch >‘9‘){ if(ch == ‘-‘) f = -1;ch=getchar(); }
 41     while(ch >= ‘0‘ && ch <= ‘9‘){ x = x*10 + ch - ‘0‘;ch = getchar(); }
 42     m = x*f;
 43 }
 44 template<class T1, class T2>
 45 void read2(T1 &a,T2 &b){read1(a);read1(b);}
 46 template<class T1, class T2, class T3>
 47 void read3(T1 &a,T2 &b,T3 &c){read1(a);read1(b);read1(c);}
 48
 49 template<class T1, class T2>
 50 inline void gmax(T1& a, T2 b){ if(a < b) a = b; }
 51 template<class T1, class T2>
 52 inline void gmin(T1&a , T2& b){ if(a > b) a = b; }
 53
 54 void debug(ll bug) { cout<<"**** "<<bug<<endl;}
 55 void bug(){ puts(" **** bug"); }
 56 void ok(){ puts(" **** ok"); }
 57 int bit[20];
 58 ll dp[20][2][20][2];
 59 ll dfs(int pos, int odd_even, int len, int zero, int on)
 60 {
 61     if(pos == 0) return odd_even^(len&1);
 62     ll ans = dp[pos][odd_even][len][zero];
 63     if(!on && ans != -1) return ans;
 64     int e = on?bit[pos]:9;
 65     ans = 0;
 66     for(int i = 0; i <= e; i++){
 67         if(zero == 1){
 68             if(i == 0) ans += dfs(pos-1, 0, 0, 1, 0);
 69             else ans += dfs(pos-1, i&1, 1, 0, on && i == e);
 70             //cout<<i<<" "<<ans<<endl;
 71         } else {
 72             if(i & 1){
 73                 if(odd_even & 1) ans += dfs(pos-1, odd_even, len+1, 0, on && i == e);
 74                 else if(len & 1) ans += dfs(pos-1, odd_even^1, 1, 0, on && i == e);
 75             } else {
 76                 if(odd_even % 2 == 0) ans += dfs(pos-1, odd_even, len+1, 0, on && i == e);
 77                 else if(len % 2 == 0) ans += dfs(pos-1, odd_even^1, 1, 0, on && i == e);
 78             }
 79         }
 80     }
 81     if(!on) dp[pos][odd_even][len][zero] = ans;
 82     return ans;
 83 }
 84 ll calc(ll x)
 85 {
 86     int top = 0;
 87     while(x){
 88         bit[++top] = x%10;
 89         x /= 10;
 90     }
 91     return dfs(top, 0, 0, 1, 1);
 92 }
 93 int main()
 94 {
 95     MS1(dp);
 96     int T, kase = 1;
 97     cin >> T;
 98     while(T--){
 99         ll L, R;
100         read2(L,R);
101         printf("Case #%d: %lld\n",kase++,calc(R) - calc(L-1));
102     }
103     return 0;
104 }
时间: 2024-08-01 17:39:05

hdu 5898 odd-even number 数位DP的相关文章

[hdu 4933]Miaomiao&#39;s Function 数位DP+大数

Miaomiao's Function Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 79    Accepted Submission(s): 18 Problem Description Firstly , Miaomiao define two functions f(x) , g(x): (K is the smallest

hdu 5623 KK&#39;s Number(dp)

问题描述 我们可爱的KK有一个有趣的数学游戏:这个游戏需要两个人,有N\left(1\leq N\leq 5*{10}^{4} \right)N(1≤N≤5∗10?4??)个数,每次KK都会先拿数.每次可以拿任意多个数,直到NN个数被拿完.每次获得的得分为取的数中的最小值,KK和对手的策略都是尽可能使得自己的得分减去对手的得分更大.在这样的情况下,最终KK的得分减去对手的得分会是多少? 输入描述 第一行一个数T\left( 1\leq T\leq 10\right)T(1≤T≤10),表示数据组

hdu 2089 不要62 (数位dp)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2089 思路:用变量记录吉利数,和最高位为2的吉利数还有不是吉利数的个数... code: #include<cstdio> #include<cstring> #include<algorithm> using namespace std; int dp[10][3]; //dp[i][j] ,i表示位数,j表示状态<pre name="code"

Hdu3079Balanced Number数位dp

枚举支点,然后就搞,记录之前的点的力矩和. #include <cstdio> #include <cstring> #include <algorithm> #include <climits> #include <string> #include <iostream> #include <map> #include <cstdlib> #include <list> #include <s

HDU 4352 XHXJ&#39;s LIS 数位DP + 状压

由LIS的nlogn解法 可以得出最后统计数组中数的个数即为LIS的长度 这样就可以状压了 #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <climits> #include <string> #include <iostream> #include <map> #include <c

HDU 4352 XHXJ&#39;s LIS 数位dp

题目链接:点击打开链接 题意: 一个数自身的最长子序列=每一位都是一个数字然后求的LIS 问区间内有多少个数 自身的最长子序列==k 思路: 因为自身的最长子序列至多=10,且由0~9组成,所以状压10个二进制表示0~9中哪些数字已经用过 dp[i][j] 表示长度为i的数字,最长子序列中出现的数字状态j的方法数.由于询问数=K,也存下来避免重复计算. #include <cstdio> #include <algorithm> #include <cstring> #

SPOJ MYQ10 Mirror Number 数位dp&#39;

题目链接:点击打开链接 MYQ10 - Mirror Number A number is called a Mirror number if on lateral inversion, it gives the same number i.e it looks the same in a mirror. For example 101 is a mirror number while 100 is not. Given two numbers a and b, find the number

HDU 4588 Count The Carries 数位DP || 打表找规律

2013年南京邀请赛的铜牌题...做的很是伤心,另外有两个不太好想到的地方....a 可以等于零,另外a到b的累加和比较大,大约在2^70左右. 首先说一下解题思路. 首先统计出每一位的1的个数,然后统一进位. 设最低位为1,次低位为2,依次类推,ans[]表示这一位上有多少个1,那么有 sum += ans[i]/2,ans[i+1] += ans[i]/2; sum即为答案. 好了,现在问题转化成怎么求ans[]了. 打表查规律比较神奇,上图不说话. 打表的代码 #include <algo

多校5 HDU5787 K-wolf Number 数位DP

1 // 多校5 HDU5787 K-wolf Number 数位DP 2 // dp[pos][a][b][c][d][f] 当前在pos,前四个数分别是a b c d 3 // f 用作标记,当现在枚举的数小于之前的数时,就不用判断i与dig[pos]的大小 4 // 整体来说就,按位往后移动,每次添加后形成的数都小于之前的数,并且相邻k位不一样,一直深搜到cnt位 5 // http://blog.csdn.net/weizhuwyzc000/article/details/5209769

HDU 4933 Miaomiao&#39;s Function(数位DP + 高精度)

题目连接 : http://acm.hdu.edu.cn/showproblem.php?pid=4933 题意 : 自己看吧,还是很容易理解的,就一个公式而已. 方法 : 比赛的时候想到两次数位DP:先对所有的数进行一次mod9 的数位DP,再得出的答案x为新的mod,再进行一次mod,后来写着写着发现似乎有点问题,对于answer = 0要特判,然后没想到好的方法,比赛就结束了. 赛后用java写了一发大数过的,对于题解中用多个大质数去判这种神奇的作法只能意会下了 , 貌似rand() 也行