zoukankan      html  css  js  c++  java
  • HDU

    题意:

      给定范围[L, R] 和 k(1~10)求范围内数位的LIS(最长上升子序列)等于k的数的个数。

    思路:

      普通的LIS做法是对于当前的数,在模拟数列中找到第一个比他大的并替换掉。

      在数位DP中需要状态压缩,其实对于每个数只有两种状态,即在模拟数列中或者不在。那么就可以用二进制(1<<10)来表示总的状态。

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    int t, k;
    int bits[20];
    ll l, r;
    ll dp[20][1<<10][11];
    bool judge(int state) {
        int cnt = 0;
        for(int i = 0; i < 10; i++)
        if(state & (1<<i)) cnt++;
        if(cnt == k) return 1;
        return 0;
    }
    int change(int state, int pos) {
        int poi = -1;
        for(int i = pos; i < 10; i++) 
        if(state & (1<<i)) {
            poi = i;
            break;
        }
        if(~poi) state -= (1<<poi);
        state += (1<<pos);
        return state;
    }
    ll dfs(int pos, int state, bool limit) {
        if(pos < 0) return judge(state);
        if((!limit) && (~dp[pos][state][k])) return dp[pos][state][k];
        int up = limit?bits[pos]:9;
        ll res = 0;
        for(int i = 0; i <= up; i++) 
        res += dfs(pos-1, state==0&&i==0?0:change(state, i), limit && up==i);
        if(!limit) dp[pos][state][k] = res;
        return res;
    }
    ll solve(ll x) {
        int pos = 0;
        while(x) {
            bits[pos++] = x%10;
            x /= 10;
        }
        return dfs(pos-1, 0, 1);
    }
    int main() {
        memset(dp, -1, sizeof(dp));
        scanf("%d", &t);
        for(int casee = 1; casee <= t; casee++) {
            scanf("%lld%lld%d", &l, &r, &k);
            printf("Case #%d: %lld
    ", casee, solve(r) - solve(l-1));
        }
    }
    View Code
  • 相关阅读:
    tp3.2小结
    tp3.2
    数据库基操
    js jq 简单做一个轮播图
    ajax加jq简单的制作一个省市编码的选择框
    hibernate的OpenSessionInViewFilter用于管理session
    EncodingServlet.java为每一个servlet设置编码方式
    mybatis的增删该查
    MyBatisUtil.java.工具类,连接数据库库
    mybatis基础知识
  • 原文地址:https://www.cnblogs.com/Pneuis/p/8120577.html
Copyright © 2011-2022 走看看