您的位置:首页 > 其它

XHXJ's LIS HDU4352(数位DP)

2015-06-18 23:17 246 查看
为在[L, R]区间中, 组成数字严格上升并且长度为K的个数

主要是状态的变化,

这里用了状态压缩来压缩一个10位数, 对于1356 长度不变的情况下如果要插入4,更具O(nlgn)

的LIS算法,会更新成1346, 是找到里面 a[i] > 4的第一个数,把他从原状态中去掉(s ^ (1 << i)) 再把x = 4 加上的情况 s‘ | (1 <<x)

/***********************************************
 * Author: fisty
 * Created Time: 2015/6/18 16:56:17
 * File Name   : hdu4352.cpp
 *********************************************** */
#include <iostream>
#include <cstring>
#include <deque>
#include <cmath>
#include <queue>
#include <stack>
#include <list>
#include <map>
#include <set>
#include <string>
#include <vector>
#include <cstdio>
#include <bitset>
#include <algorithm>
using namespace std;
#define Debug(x) cout << #x << " " << x <<endl
#define Memset(x, a) memset(x, a, sizeof(x))
const int INF = 0x3f3f3f3f;
typedef long long LL;
typedef pair<int, int> P;
#define FOR(i, a, b) for(int i = a;i < b; i++)
#define MAX_N 21
int t;
LL L, R, K;
int digit[MAX_N];

LL f[MAX_N][1<<10][MAX_N];

int getcount(int x){
    int sum = 0;
    while(x){
        if(x & 1) sum++;
        x >>= 1; 
    }
    return sum;
}
int getnew(int x, int s){
    for(int i = x;i < 10; i++){
        //寻找s中比x 大的第一个数 i
        if(s & (1<<i)){
            //如果找到,先在s中去掉这个数,再把 x 加上
            return (s ^ (1<<i)) | (1 << x);
        }
    }
    return s | (1 << x);  //没有找到比x大的数,直接把x加上
}
LL dfs(int len, int s, int e, int zero){
    if(len < 0) return getcount(s) == K;
    if(!e && f[len][s][K] != -1) return f[len][s][K];
     
    LL ans = 0;
    int u = e ? digit[len] : 9;
    for(int d = 0; d <= u; d++){
        int z = zero && (d == 0);
        ans += dfs(len-1, z ? 0 : getnew(d, s), e && (d == u), z);
    }
    if(!e) f[len][s][K] = ans;
    return ans;
}
LL solve(LL x){
    int len = 0;
    while(x){
        digit[len++] = x % 10;
        x /= 10;
    }
    return dfs(len-1, 0, 1, 1);
}
int main(){
    //freopen("in.cpp", "r", stdin);
    cin.tie(0);
    ios::sync_with_stdio(false);
    cin >> t;
    int cnt = 1;
    Memset(f, -1);
    while(t--){
        cin >> L >> R >> K;
        cout << "Case" << " #" << cnt++ << ": ";
        cout << solve(R) - solve(L-1) << endl;
    }
    return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: