51nod 1623 完美消除(数位DP)
2017-12-13 20:41
295 查看
首先考虑一下给一个数如何求它需要多少次操作。
显然用一个单调栈就可以完成:塞入栈中,将比它大的所有数都弹出,如果栈中没有当前数,答案+1。
因为数的范围只有0~9,所以我们可以用一个二进制数来模拟这个栈,并塞到DP的状态里。
设$dp[i][j][k]$表示前i位数,已经进行了j次操作,栈的状态为k的方案数。
每次枚举一个数的时候,先把比这个数大的数在状态中都清零,再看看状态中有没有这个数,没有的话答案+1。
注意需要把状态初始值设为0在栈中...T T
#include<iostream> #include<cstring> #include<cstdlib> #include<cstdio> #define ll long long using namespace std; ll l, r, K; ll dp[20][20][1<<10]; int a[20]; ll dfs(int pos, int k, int st, bool limit) { if(!pos) return k==K; if(!limit && dp[pos][k][st]!=-1) return dp[pos][k][st]; int up=limit?a[pos]:9; ll ans=0; for(int i=0;i<=up;i++) { int now=st; for(int j=i+1;j<=9;j++) now^=((now & (1<<j))!=0)<<j; if(st&(1<<i)) ans+=dfs(pos-1, k, now, limit && i==up); else if(k<K) ans+=dfs(pos-1, k+1, now|(1<<i), limit && i==up); } if(!limit) dp[pos][k][st]=ans; return ans; } ll solve(ll x) { int pos=0; while(x) a[++pos]=x%10, x/=10; return dfs(pos, 0, 1, 1); } int main() { memset(dp, -1, sizeof(dp)); scanf("%lld%lld%lld", &l, &r, &K); printf("%lld\n", solve(r)-solve(l-1)); }View Code
相关文章推荐
- 51NOD 1623 完美消除 数位DP
- 51 nod 1623 完美消除(单调栈+数位DP)
- 51nod1623完美消除 【数位dp】
- 51nod 完美消除 DP
- 51nod 1623:完美消除
- 51nod1623 完美消除 (数位dp)
- 51Nod-1623-完美消除
- 51nod:数字1的数量(线性dp or 数位dp)
- 51nod 1043 幸运号码(数位dp
- 【数位dp入门】51nod 1009 数字1的数量
- 51Nod 数字0到9的数量 (数位DP)
- 51nod 1042 数位dp
- 51nod 1009 数字1的数量(数位dp)
- 51nod:第K个幸运排列(数位dp & 逆康托展开)
- 【51Nod】1043 - 幸运号码(数位dp)
- 51nod 1043 数位dp
- 51nod 1042 数字0-9的数量(数位DP)
- 51nod-1009-数位dp
- 51Nod 1009 数字1的数量(数位dp)
- 51Nod 1009 1042 数位DP