hdu 4352 数位DP

来源:互联网 发布:图片透视软件 编辑:程序博客网 时间:2024/04/30 19:09
题意:

给定区间[l,r]为这个区间内最长递增子序列恰好是K的数字有多少

#include <cstdio>#include <cstring>#include <algorithm>#include <iostream>using namespace std;#define LL __int64LL l, r;int k;int a[25];LL dp[25][11][(1<<10)+3];LL dfs(int len, int num, int zt, int lim) {    if(!len) return num == k;    if(!lim && ~dp[len][k][zt]) return dp[len][k][zt]; // 想想状态转移,注意这里有一维是k不是num。    int m = lim ? a[len-1] : 9;    int i, j;    LL ret = 0;    for(i = 0; i <= m; i++) {        if(!zt && !i)            ret += dfs(len-1, 0, 0, 0); // 去掉前导0        else {            if(zt < (1<<i))                ret += dfs(len-1, num+1, zt|(1<<i), lim&&i==m);            else if(zt & (1<<i))                ret += dfs(len-1, num, zt, lim&&i==m);            else {                for(j = i+1; j <= 9; j++)                    if(zt&(1<<j)) {                        ret += dfs(len-1, num, (zt|(1<<i))^(1<<j), lim&&i==m);                        break;                    }            }        }    }    if(!lim) dp[len][k][zt] = ret;    return ret;}LL gao(LL n) {    int len = 0;    while(n) { a[len++] = n%10; n/=10; }    return dfs(len, 0, 0, 1);}int main() {    int cas;    memset(dp, -1, sizeof(dp));    cin >> cas;    for(int ca = 1; ca <= cas; ca++) {        cin >> l >> r >> k;        printf("Case #%d: %I64d\n", ca, gao(r) - gao(l-1));    }    return 0;}


原创粉丝点击