zoukankan      html  css  js  c++  java
  • XHXJ's LIS

    题目链接:https://vjudge.net/problem/HDU-4352

    题意:题目意思就是给你L到R区间,和一个数字K,然后让你求L到R区间之内满足最长上升子序列长度为K的数字有多少个;

    思路:dp[i][j][k]表示前i位,用二进制表示最长上升子序列都出现了那些数,最长上升子序列的长度为K。每次对新加的数字进行判断,看如果他前面一个数字是否比他小,那就替换,没有就将其加入。

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    ll dp[25][1<<10][25];
    int a[20];
    ll k;
    int fun(int s)
    {
        int sum=0;
        while(s)
        {
            if(s%2==1)
                sum++;
            s/=2;
        }
        return sum;
    }
    int getnews(int x,int s)
    {
        for(int i=x;i<10;i++)
        {
            if(s&(1<<i))
               return s^(1<<i)|(1<<x);
        }
        return s|(1<<x);
    }
    //len代表当前枚举的位,s表示哪些数已经选过了的状态,flag代表是否还是处于上边界,qd表示是否为前导0
    ll dfs(int len,int s,bool flag,bool qd)
    {
        if(len==0)
            return fun(s)==k;
        int up=flag?a[len]:9;//决定你枚举的上界是多少
        if(!flag&&dp[len][s][k]!=-1)
            return dp[len][s][k];//如果不是处于上边界并且之前求过了值的话可以直接返回
        ll tmp=0;
        for(int i=0; i<=up; i++)
        {
            tmp+=dfs(len-1,(qd&&i==0)?0:getnews(i,s),flag&&i==a[len],qd&&(i==0));
        }
        if(!flag)
            dp[len][s][k]=tmp;//求了值用dp存下,下次可以使用
        return tmp;
    }
    ll suan(ll x)
    {
        int pos=0;
        while(x)
        {
            a[++pos]=x%10;
            x/=10;
        }
        return dfs(pos,0,true,true);
    }
    int main()
    {
        ll l,r;
        memset(dp,-1,sizeof(dp));
        int t,u=0;
        cin>>t;
        while(t--)
        {
            cin>>l>>r>>k;
            printf("Case #%d: ",++u);
            cout<<suan(r)-suan(l-1)<<endl;
        }
    }
  • 相关阅读:
    基于Kubernates微服务案例
    领导人怎样带领好团队
    前端性能核对表Checklist-2018
    国际巨头互联网公司一些运营与管理思路
    IT研发工程师职业规划
    高性能风控数据平台设计
    基础设施DevOps演进之路
    2017-2018年Scrum状态调查报告
    大型互联网系统的监控流水线
    小程序【情书与歌】一小时过审经验小谈
  • 原文地址:https://www.cnblogs.com/zcb123456789/p/13678619.html
Copyright © 2011-2022 走看看