HDU odd-even number 数位dp
生活随笔
收集整理的這篇文章主要介紹了
HDU odd-even number 数位dp
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
題意
在l到r區間內求有多少個符合條件“當前數中所有連續的奇數長度是偶數 所有連續的偶數長度是奇數”的個數分析
典型的數位dp問題 我們設置dp數組時可以根據 dp[pos][pre][len]設定 表示在pos長度下 前面是pre并且長度是len的個數共有多少這個方法很巧妙 根據這個結構 我們dfs(pos,pre,len,zero,limit)這樣設置遞歸參數 我們把所有可能符合條件的分支都去搜索一遍 當我們到pos==0的時候 判斷一下 此時如果pre和len的奇偶性不同 那么就返回1 表示這個數字 符合條件 因為當我們遞歸的時候是把所有可能的嘗試都去做了一遍 所以如果當下的數 可能產生正確結果 就根據我們設置的dfs結構遞歸下去 最終都依靠 pos==0的判斷 和之前所做的備忘得到結果 和縮小時間復雜度code
#include<bits/stdc++.h> using namespace std; typedef long long ll; int d[20];//1 2 3 4 5 6 7 8 9 10 ll dp[20][20][20]; ll dfs(int pos,int pre,int len,bool zero,bool lim){if(pos==0)return (pre&1)!=(len&1);if(!lim&&~dp[pos][pre][len])return dp[pos][pre][len];ll ans=0;int up = lim==0?9:d[pos];for(int i=0;i<=up;i++){//為了計算得到正確結果 我們嘗試把所有可能產生計數的可能都走一遍if(zero){//如果存在前導0 那么可能產生計數的情況是 當前位=0或!=0 都要搜索一遍if(i==0)ans+=dfs(pos-1,0,0,1,i==up&&lim);//當前位為0 那么繼續加一位前導0繼續搜索else ans+=dfs(pos-1,i,len+1,0,i==up&&lim);//非0 zero=0繼續搜索 }else{if(i&1){//如果是奇數if(pre&1)ans+=dfs(pos-1,i,len+1,0,i==up&&lim);//繼續搜索else if(len&1)ans+=dfs(pos-1,i,1,0,i==up&&lim);//如果是偶數 長度是也是奇數 那么改變奇偶性 長度為1 繼續搜}else{if(!(pre&1))ans+=dfs(pos-1,i,len+1,0,i==up&&lim);//如果上一位偶數 那么長度遞增 繼續搜else if(!(len&1))ans+=dfs(pos-1,i,1,0,i==up&&lim);//如果上一位是奇數 長度變1繼續搜 }}}if(!lim)dp[pos][pre][len]=ans;return ans; } ll solve(ll x){int j=0;while(x){d[++j] = x%10;x/=10;}return dfs(j,0,0,1,1); } int main() {int t;ll l,r;scanf("%d",&t);for(int i=1;i<=t;i++){scanf("%lld%lld",&l,&r);printf("Case #%d: ",i);memset(dp,-1,sizeof(dp));printf("%lld\n",solve(r)-solve(l-1));}return 0; }總結
以上是生活随笔為你收集整理的HDU odd-even number 数位dp的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: R语言F分布
- 下一篇: Oracle中分区表中表空间属性