1. 程式人生 > >Hdu 3555 Bomb 數位dp

Hdu 3555 Bomb 數位dp

文章目錄

題目連結

題意

求1 to n有多少個含有49的數.

題解

我好像一年前就A了此題,不過貌似還是不怎麼懂. 令dp[i][0]dp[i][0]表示ii位數中不含有連續4949的數字個數. dp[i][1]dp[i][1]表示ii位數中不含有連續4949,但是首位是99的數字個數. dp[i][2]dp[i][2]表示ii位數中含有連續4949的數字個數. 我們先預處理這個dpdp陣列. dp[i][0]=dp[i-1][0]*10-dp[i-1][1]. 可以在前面隨便加一個數字,但是當首位是99的時候你就不能加4

4,否則出現4949,因此要把首位是99且加了44的方法去掉. dp[i][1]=dp[i-1][0].在前面加一個99. dp[i][2]=dp[i-1][2]*10+dp[i-1][1]. 對於已經有4949的數字,可以在前面隨便加.對於首位是99的數字,加一個44也是可以的,這部分要加上. 接下來給出nn,進行solvesolve. 我們將nn的每一位加入陣列bitbit,從高位到低位開始列舉. 定義一個boolbool型變數niconico表示當前位是否已經出現了4949. 首先i1i-1位的數字中含有4949的要被加上,數量乘以b
it[i]bit[i]
(0bit[i]10\to bit[i]-1均可取). 然後如果nn自己有4949,後面沒有4949的數字也可以加入戰鬥,數量乘以bit[i]bit[i]. 如果niconico00,但是bit[i]>4bit[i]>4,當bit[i]bit[i]44的時候,後面有99是可以的,還要加上dp[i1][1]dp[i-1][1]. 最後判斷nn中是否出現了4949,如果出現了,把niconico變成11.

#include
<bits/stdc++.h>
//Ithea Myse Valgulious namespace chtholly{ typedef long long ll; #define re0 register int #define rec register char #define rel register ll #define gc getchar #define pc putchar #define p32 pc(' ') #define pl puts("") /*By Citrus*/ inline int read(){ int x=0,f=1;char c=gc(); for (;!isdigit(c);c=gc()) f^=c=='-'; for (;isdigit(c);c=gc()) x=(x<<3)+(x<<1)+(c^'0'); return f?x:-x; } template <typename mitsuha> inline bool read(mitsuha &x){ x=0;int f=1;char c=gc(); for (;!isdigit(c)&&~c;c=gc()) f^=c=='-'; if (!~c) return 0; for (;isdigit(c);c=gc()) x=(x<<3)+(x<<1)+(c^'0'); return x=f?x:-x,1; } template <typename mitsuha> inline int write(mitsuha x){ if (!x) return 0&pc(48); if (x<0) x=-x,pc('-'); int bit[20],i,p=0; for (;x;x/=10) bit[++p]=x%10; for (i=p;i;--i) pc(bit[i]+48); return 0; } inline char fuhao(){ char c=gc(); for (;isspace(c);c=gc()); return c; } }using namespace chtholly; using namespace std; ll dp[99][3]; int main(){ int i,t; for (**dp=i=1;i<=20;++i){ dp[i][0]=dp[i-1][0]*10-dp[i-1][1]; dp[i][1]=dp[i-1][0]; dp[i][2]=dp[i-1][2]*10+dp[i-1][1]; } for (t=read();t--;){ ll n; read(n),++n; /*這裡的n為什麼要+1呢?對於其他情況來說,不影響答案,但是當n裡本就有49的時候,第三個判斷要bit[i]>4才能過,但是剛好為49的時候是個例外.*/ int bit[25]={0},p=0; for (;n;n/=10) bit[++p]=n%10; bool nico=0; ll llx=0; for (i=p;i;--i){ llx+=dp[i-1][2]*bit[i]; if (nico) llx+=dp[i-1][0]*bit[i]; if (!nico&&bit[i]>4) llx+=dp[i-1][1]; if (bit[i]==9&&bit[i+1]==4) nico=1; } write(llx),pl; } }

謝謝大家.