HDU 5898 odd-even number 数位dp
2016-09-19 14:00
267 查看
题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=5898odd-even number
Time Limit: 2000/1000 MS (Java/Others)Memory Limit: 65536/65536 K (Java/Others)问题描述
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).
输入
First line a t,then t cases.every line contains two integers L and R.
输出
Print the output for each case on one line in the format as shown below.
样例输入
2
1 100
110 220
样例输出
Case #1: 29
Case #2: 36
题意
求[l,r]区间里面满足任意连续个数位为偶数的长度为奇数,任意连续个数位为奇数的长度为偶数,比如110,1100033334等。
题解
数位dp具体看代码注释
#include<map> #include<set> #include<cmath> #include<queue> #include<stack> #include<ctime> #include<vector> #include<cstdio> #include<string> #include<bitset> #include<cstdlib> #include<cstring> #include<iostream> #include<algorithm> #include<functional> using namespace std; #define X first #define Y second #define mkp make_pair #define lson (o<<1) #define rson ((o<<1)|1) #define mid (l+(r-l)/2) #define sz() size() #define pb(v) push_back(v) #define all(o) (o).begin(),(o).end() #define clr(a,v) memset(a,v,sizeof(a)) #define bug(a) cout<<#a<<" = "<<a<<endl #define rep(i,a,b) for(int i=a;i<(b);i++) #define scf scanf #define prf printf typedef long long LL; typedef vector<int> VI; typedef pair<int,int> PII; typedef vector<pair<int,int> > VPII; const int INF=0x3f3f3f3f; const LL INFL=0x3f3f3f3f3f3f3f3fLL; const double eps=1e-6; const double PI = acos(-1.0); //start---------------------------------------------------------------------- const int maxn=22; int arr[maxn],tot; LL dp[maxn][2][2]; ///dp[i][0][0]表示长度为i,最后偶数位为偶数的情况 ///dp[i][0][1]表示长度为i,最后奇数位为偶数的情况 ///dp[i][1][0]表示长度为i,最后偶数位为奇数的情况 ///dp[i][1][1]表示长度为i,最后奇数位为奇数的情况 LL dfs(int len,int x,int y,bool ismax,bool iszer) { if (len == 0) { ///递归边界 return y^1; } if (!ismax&&!iszer&&dp[len][x][y]>=0) return dp[len][x][y]; LL res = 0; int ed = ismax ? arr[len] : 9; ///这里写递推的代码 if(x==0){ for(int i=0;i<=ed;i+=2){ if(i==0&&iszer){ ///处理前导零 res+=dfs(len-1,0,1,ismax&&i==ed,iszer&&i==0); res+=dfs(len-1,1,0,ismax&&i==ed,iszer&&i==0); } else{ ///后面接的还是偶数的情况 res+=dfs(len-1,0,y^1,ismax&&i==ed,iszer&&i==0); ///后面能接奇数的情况 if(y==1&&len>1) res+=dfs(len-1,1,0,ismax&&i==ed,iszer&&i==0); } } }else{ for(int i=1;i<=ed;i+=2){ ///后面接的还是奇数的情况 res+=dfs(len-1,1,y^1,ismax&&i==ed,iszer&&i==0); ///后面接的是偶数的情况 if(y==1&&len>1) res+=dfs(len-1,0,1,ismax&&i==ed,iszer&&i==0); } } ///这里记忆化存的必须保证没有前导零的情况!,有前导零的要单独计算 return ismax||iszer ? res : dp[len][x][y] = res; } LL solve(LL x) { tot = 0; while (x) { arr[++tot] = x % 10; x /= 10; } LL even=dfs(tot, 0,1, true,true); LL odd=dfs(tot,1,0,true,true); return even+odd; } void init(){ clr(dp,-1); } int main() { int tc,kase=0; scf("%d",&tc); init(); while(tc--){ LL x,y; scf("%lld%lld",&x,&y); prf("Case #%d: %lld\n",++kase,solve(y)-solve(x-1)); } return 0; } //end-----------------------------------------------------------------------
再回顾一发:
#include<map> #include<set> #include<cmath> #include<queue> #include<stack> #include<ctime> #include<vector> #include<cstdio> #include<string> #include<bitset> #include<cstdlib> #include<cstring> #include<iostream> #include<algorithm> #include<functional> using namespace std; #define X first #define Y second #define mkp make_pair #define lson (o<<1) #define rson ((o<<1)|1) #define mid (l+(r-l)/2) #define sz() size() #define pb(v) push_back(v) #define all(o) (o).begin(),(o).end() #define clr(a,v) memset(a,v,sizeof(a)) #define bug(a) cout<<#a<<" = "<<a<<endl #define rep(i,a,b) for(int i=a;i<(b);i++) #define scf scanf #define prf printf typedef long long LL; typedef vector<int> VI; typedef pair<int,int> PII; typedef vector<pair<int,int> > VPII; const int INF=0x3f3f3f3f; const LL INFL=10000000000000000LL; const double eps=1e-9; const double PI = acos(-1.0); //start---------------------------------------------------------------------- LL dp[22][3][2]; int arr[22],tot; ///k==0表示上一位不存在,k==1表示上一位为奇数,k==2表示上一位为偶数 ///l==0表示上一位连续偶数个奇数或偶数的情况 LL dfs(int len,int k,int l, bool ismax,bool iszer) { if (len == 0) { if(l==0) return 1LL; return 0; } if (!ismax&&dp[len][k][l]>=0) return dp[len][k][l]; LL res = 0; int ed = ismax ? arr[len] : 9; ///这里插入递推公式 for (int i = 0; i <= ed; i++) { if(i==0&&iszer){ ///处理前导零 res+=dfs(len-1,0,0,ismax&&i==ed,iszer&&i==0); }else{ if(k==0){ if(i&1) res+=dfs(len-1,1,1,ismax&&i==ed,iszer&&i==0); else res+=dfs(len-1,2,0,ismax&&i==ed,iszer&&i==0); }else if(k==1){ if(i&1){ res+=dfs(len-1,k,l^1,ismax&&i==ed,iszer&&i==0); }else{ if(l==0) res+=dfs(len-1,2,0,ismax&&i==ed,iszer&&i==0); } }else if(k==2){ if(!(i&1)){ res+=dfs(len-1,k,l^1,ismax&&i==ed,iszer&&i==0); }else{ if(l==0) res+=dfs(len-1,1,1,ismax&&i==ed,iszer&&i==0); } } } } return ismax ? res : dp[len][k][l] = res; } LL solve(LL x) { tot = 0; while (x) { arr[++tot] = x % 10; x /= 10; } return dfs(tot,0,0,true,true); } int main() { clr(dp,-1); int tc,kase=0; scf("%d",&tc); while(tc--){ LL l,r; scf("%lld%lld",&l,&r); prf("Case #%d: %lld\n",++kase,solve(r)-solve(l-1)); } return 0; } //end-----------------------------------------------------------------------
精简版:
#include<map> #include<set> #include<cmath> #include<queue> #include<stack> #include<ctime> #include<vector> #include<cstdio> #include<string> #include<bitset> #include<cstdlib> #include<cstring> #include<iostream> #include<algorithm> #include<functional> using namespace std; #define X first #define Y second #define mkp make_pair #define lson (o<<1) #define rson ((o<<1)|1) #define mid (l+(r-l)/2) #define sz() size() #define pb(v) push_back(v) #define all(o) (o).begin(),(o).end() #define clr(a,v) memset(a,v,sizeof(a)) #define bug(a) cout<<#a<<" = "<<a<<endl #define rep(i,a,b) for(int i=a;i<(b);i++) #define scf scanf #define prf printf typedef long long LL; typedef vector<int> VI; typedef pair<int,int> PII; typedef vector<pair<int,int> > VPII; const int INF=0x3f3f3f3f; const LL INFL=10000000000000000LL; const double eps=1e-9; const double PI = acos(-1.0); //start---------------------------------------------------------------------- LL dp[22][3][2]; int arr[22],tot; ///k==0表示上一位不存在,k==1表示上一位为奇数,k==2表示上一位为偶数 ///l==0表示上一位连续偶数个奇数或偶数的情况 LL dfs(int len,int k,int l, bool ismax,bool iszer) { if (len == 0) return l^1; if (!ismax&&dp[len][k][l]>=0) return dp[len][k][l]; LL res = 0; int ed = ismax ? arr[len] : 9; for (int i = 0; i <= ed; i++) { if(i==0&&iszer){ res+=dfs(len-1,2,0,ismax&&i==ed,iszer&&i==0); }else{ if(k==2){ if(i&1) res+=dfs(len-1,1,1,ismax&&i==ed,iszer&&i==0); else res+=dfs(len-1,0,0,ismax&&i==ed,iszer&&i==0); }else{ if(!(k^(i&1))) res+=dfs(len-1,k,l^1,ismax&&i==ed,iszer&&i==0); else if(!l) res+=dfs(len-1,!k,!k,ismax&&i==ed,iszer&&i==0); } } } return ismax ? res : dp[len][k][l] = res; } LL solve(LL x) { tot = 0; while (x) { arr[++tot] = x % 10; x /= 10; } return dfs(tot,2,0,true,true); } int main() { clr(dp,-1); int tc,kase=0; scf("%d",&tc); while(tc--){ LL l,r; scf("%lld%lld",&l,&r); prf("Case #%d: %lld\n",++kase,solve(r)-solve(l-1)); } return 0; } //end-----------------------------------------------------------------------
Notes
数位dp,比赛的时候思路歪了,干了两个多小时没出样例。。第二天条整思路之后,又调了一个上午。。。。orz,dp弱渣。。。
相关文章推荐
- hdu 5898 odd-even number 数位DP
- hdu 5898 odd-even number(基础数位DP)
- HDU 5898 odd-even number (数位DP)
- HDU 5898 odd-even number(数位dp)
- hdu_5898_odd-even number(数位DP)
- HDU 5898 odd-even number——数位dp
- HDU 5898 odd-even number 数位DP
- 【2016-沈阳赛区网络赛-G】记忆化搜索,数位DP(odd-even number,hdu 5898)
- HDU 5898 odd-even number(数位DP)
- HDU 5898 odd-even number (数位DP) -2016 ICPC沈阳赛区网络赛
- HDU 5898 odd-even number(数位dp)
- hdu 5898 odd-even number (数位dp)
- [hdu 5898 odd-even number] 数位DP
- hdu 5898 odd-even number (数位dp)
- hdu 5898 - odd-even number (2016沈阳网络赛) - 数位dp
- HDU 5898 odd-even number (数位DP)
- hdu 5898 odd-even number 数位dp
- hdu 5898 odd-even number (数位dp 沈阳网络赛)
- HDU 5898 odd-even number (数位DP) 2016 ACM/ICPC Asia Regional Shenyang Online
- HDU 5898 odd-even number (数位DP) 2016 ACM/ICPC Asia Regional Shenyang Online