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).
InputFirst line a t,then t cases.every line contains two integers L and R.OutputPrint the output for each case on one line in the format as shown below.Sample Input
2 1 100 110 220Sample Output
Case #1: 29 Case #2: 36
数位dp学习题。
代码:
#include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #define MAX 200005 #define inf 0x3f3f3f3f using namespace std; long long dp[20][2][2],bound[20]; long long dfs(int pos,int pre,int ispre,bool lead,bool limit)///pos表示位置 从高位开始 pre表上上一位的1奇0偶性 ispre表示上一位奇偶性连续个数的奇偶性 lead前导0 { if(pos == -1)return (pre ^ ispre);///最低一位也过了判断 最后这一串连续的 奇数或偶数的 个数奇偶性是否满足 满足返回真 if(!limit && !lead && dp[pos][pre][ispre] != -1)return dp[pos][pre][ispre];///如果没限制 也不是 前导 0 dp当前位置还记录过 直接返回 int up = (limit ? bound[pos] : 9);///确定当前位的限制 如果上一位到了限制位 那么这一位也需要限制(比如120,百位是1的情况下十位最高是2,百位不足1,十位可以到9) long long ans = 0;///记录之后位的满足个数 for(int i = 0;i <= up;i ++) { if(lead && !i)ans += dfs(pos - 1,1,0,true,limit && i == up);///前导0 不算在内 else if(!(i % 2 ^ pre))ans += dfs(pos - 1,pre,ispre ^ 1,false,limit && i == up);///奇偶性与上一位相同 else if((i % 2 ^ pre) && (pre ^ ispre))ans += dfs(pos - 1,i % 2,1,false,limit && i == up);///奇偶性不同 且上一位奇偶性的连续个数的奇偶性正确 不然没必要继续 } if(!limit && !lead)dp[pos][pre][ispre] = ans;///无限制 无前导0 可以记录 方便下次直接返回 return ans; } long long solve(long long t) { long long c = 0; while(t) { bound[c ++] = t % 10; t /= 10; } return dfs(c - 1,1,0,true,true);///为了能进入下一层 pre 和 ispre不能相同 相当于前导0 } int main() { long long l,r; int n; memset(dp,-1,sizeof(dp)); scanf("%lld",&n); for(int i = 1;i <= n;i ++) { scanf("%lld%lld",&l,&r); printf("Case #%d: %lld ",i,solve(r) - solve(l - 1)); } }