HDU.4352.XHXJ's LIS(數位DP 狀壓 LIS)
阿新 • • 發佈:2018-09-26
type 2.x main 個數 %d std ret href n)
題目鏈接
數位DP。
至於怎麽求LIS,因為只有10個數,所以可以參照O(nlogn)求LIS的方法,狀壓記錄狀態。
每次加一個數和求LIS一樣更新狀態。最後狀態中1的個數就是LIS的長度。
//93MS 3004K #include <cstdio> #include <cctype> #include <cstring> #include <algorithm> #define gc() getchar() typedef long long LL; const int N=(1<<10)+3; int K,bit[21]; LL f[21][N][12];//f[i][j][k] 當前到i位 狀態為j K為k(這個可以保留) bool vis[21][N][12]; inline LL read() { LL now=0;register char c=gc(); for(;!isdigit(c);c=gc()); for(;isdigit(c);now=now*10+c-'0',c=gc()); return now; } inline int Count(int x) { int res=0; for(; x; res+=x&1,x>>=1); return res; } inline int Upd(int s,int x)//替換掉第一個>=x的位 { for(int i=x; i<10; ++i) if(s>>i&1) return (s^(1<<i))|(1<<x); return s|(1<<x); } LL DFS(int x,bool lim,bool lead,int s) { if(!x) return Count(s)==K; if(!lim && vis[x][s][K]) return f[x][s][K];//就算有前導零也是可以直接返回啊(本題s狀態沒變就沒影響) LL res=0; int up=lim?bit[x]:9; for(int i=0; i<=up; ++i) res+=DFS(x-1,lim&&i==up,lead&&!i,(lead&&!i)?0:Upd(s,i)); if(!lim) vis[x][s][K]=1, f[x][s][K]=res; return res; } LL Calc(LL x) { int cnt=0; for(; x; x/=10) bit[++cnt]=x%10; if(cnt<K) return 0; return DFS(cnt,1,1,0); } inline LL Solve() { LL l=read(),r=read(); K=read(); return Calc(r)-Calc(l-1); } int main() { for(int i=1,T=read(); i<=T; printf("Case #%d: %lld\n",i++,Solve())); return 0; }
HDU.4352.XHXJ's LIS(數位DP 狀壓 LIS)