• HDU4352 (数位dp)


    For example, when she see a number, she would think whether the digits of a number are strictly increasing. If you consider the number as a string and can get a longest strictly increasing subsequence the length of which is equal to k, the power of this number is k.. It is very simple to determine a single number’s power, but is it also easy to solve this problem with the numbers within an interval? xhxj has a little tired,she want a god cattle to help her solve this problem,the problem is: Determine how many numbers have the power value k in [L,R] in O(1)time.

    InputFirst a integer T(T<=10000),then T lines follow, every line has three positive integer L,R,K.( 

    0<L<=R<2 63-1 and 1<=K<=10).OutputFor each query, print "Case #t: ans" in a line, in which t is the number of the test case starting from 1 and ans is the answer.

    Sample Input

    1
    123 321 2

    Sample Output

    Case #1: 139 

    题意

    求[L,R]中符合最长上升子序列为k的个数,一开始以为子序列是连续的,导致疯狂wa,qwq。

    题解

    思路:
    dp[pos][sta][k]
    pos:搜索到第几位
    sta:之前的最长上升子序列的状态。
    k:就是输入的那个k

    此题的难点就在于中间的那一维--sta。
    sta的二进制每一位,都对应了数位上的一个数字。
    举例来说:如果sta按照数字13425来更新。
    首先遇到1,变成 0100000000 (或者0000000010,其实这是完全一样的,只要保证不同状态的sta不一样就行了)
    然后遇到3,很明显,之前没有比3更大的数字,然后变成0101000000

    遇到4,sta变成0101100000

    在这里打断一下,不能看出,sta中1的个数,就是LIS的长度。

    然后遇到2,这时大于等于2的有一个3.于是把3的二进制1交给2,sta变成0110100000
    为什么这么做?????
    首先我们知道,这样做绝不会改变1的个数,如果之前出现过2,那么sta就不会变化,否则就把之后最近的那个1挪到当前位置。
    然后再看这4个数字:1342
    如果之后出现的数字有比这四个数字都大的,那么之前究竟是1243还是1342都对后方的更新没有影响了。
    就如同例子中的5,它只需知道,在之前出现的数字中最大的没有自己大就行了,因为只要这样,就可把5位置的0变成1。
    注意:如果有多种状态,( 1243 ,1342 ),只要对后续影响相同,就可以看做同一种状态。

    如果之后出现的数字没有比这四个数都大的,那么还是不会改变1的个数。
    但是,出现数字2的时候,第二个1向前挪了一位,这实际上是把LIS为2的序列由13变成了12,这里对后续的影响是不同的,可以手推323来解答你的困惑。

    于是到此我们就知道了sta的真正含义。
    如果sta的第a位上为1,并且之前(包括自己)有b个1,那么长度为b的上升序列的末尾的最小值就是a

    这里还要判断前面是不是有前导0,不然01会被当成LIS是2,但是其实是1.

    代码
    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    #define rep(i,a,b) for(int i=(a);i<=(b);i++)
    #define mes(p,b) memset(p,b,sizeof(p))
    int t,k,a[20];ll l,r,dp[20][1025][11];
    int new_sta(int x,int n){
        rep(i,n,9){
            if((1<<i)&x) return (x^(1<<i))|(1<<n);
        }
        return x|(1<<n);
    }
    int cal(int x){
        int cnt=0;
        while(x){
            cnt+=x&1;
            x>>=1;
        }
        return cnt;
    }
    ll dfs(int pos,int sta,bool limit,bool lead){
        if(pos==-1) return cal(sta)==k;
        if(!limit&&!lead&&dp[pos][sta][k]!=-1)  return dp[pos][sta][k];
        int up=limit?a[pos]:9;
        ll ans=0;
        rep(i,0,up){
            ans+=dfs(pos-1,(lead&&i==0)?0:new_sta(sta,i),limit&&i==up,lead&&!i);
        }
        if(!limit&&!lead) dp[pos][sta][k]=ans;
        return ans;
    }
    ll solve(ll x){
        int pos=-1;
        while(x>0){
            a[++pos]=x%10;
            x/=10;
        }
        return dfs(pos,0,1,1);
    }
    int main()
    {
      ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
      cin>>t;
      mes(dp,-1);
      rep(i,1,t){
          cin>>l>>r>>k;
          cout<<"Case #"<<i<<": "<<solve(r)-solve(l-1)<<endl;
      }
      return 0;
    }
     
  • 相关阅读:
    C# 基本数据类型
    java二进制,原码、反码、补码、位运算
    .net邮件发送[c#]
    linux软件安装命令
    VB.net实现从ListView控件中异地获取文本内容源代码
    VB获得进程PID
    任意组合指令达到免杀
    免杀之等价替换法
    ASP技巧base64编码、解码函数
    看到一个思路新颖的下载者制作法
  • 原文地址:https://www.cnblogs.com/FZUlh/p/12269493.html
Copyright © 2020-2023  润新知