• UESTC_邱老师选妹子(二) 2015 UESTC Training for Dynamic Programming<Problem I>


    I - 邱老师选妹子(二)

    Time Limit: 3000/1000MS (Java/Others)     Memory Limit: 65535/65535KB (Java/Others)
     

    邱老师长得帅这是人尽皆知,于是追他的妹子就会很多。但是你知道,邱老师是一个很专一的人,所以他心里面只能有一个人。于是他决定从追他的众多妹子里挑选一个出来。

    在第一轮的选拔中,剩余了一些妹子。酱神又给邱老师出主意了,因为最近酱神刚刚学习了最长上升子序列,所以这次,依然是把妹子们编号,从l到r,一共r-l+1个,这次要求妹子的

    编号按照字符来处理,使得最长上升子序列正好是k,比如123是3,321是1.

    求剩下的妹子的个数

    Input

    一开始是一个整数t<=1000,表示的是数据组数,接下来t行,每行是l,r,k 0<l<=r<2^63-1 1<=k<=10

    Output

    每组数据输出占一行,为一个整数,表示剩下的妹子的个数

    Sample input and output

    Sample InputSample Output
    1
    123 321 2
    139

    解题思路:

    贪心维护最长上升子序列即可

     f(i,f1,f2,f3,k)

      i  -> 正在转移第 i 位

      f1 -> 前面是否大于过下界

      f2 -> 前面是否小于过上界

      f3 -> 是否有前导0

      k  -> 前面出现的数的集合 (贪心维护最大)

    为什么这样是正确的呢?

     我们考虑这样的数字 1 4 3

     我们认为最长上升显然是 1 3 ,而不会考虑到1 4,这样可以保证不会遗漏解,故是正解的

    #include <iostream>
    #include <algorithm>
    #include <cstring>
    #include <cstdio>
    typedef long long ll;
    using namespace std;
    
    int tark,maxlen;
    string A,B;
    ll f[22][2][2][2][1<<10];
    
    inline int GetLength(int k)
    {
       int len = 0;
       for(int i = 0 ; i < 10 ; ++ i)
        if (k >> i & 1)
         len++;
       return len;
    }
    
    inline int tanxinset(int k,int pos) //贪心维护 
    {
       for(int i = pos ; i < 10 ; ++ i)    
        if (k >> i & 1)
         return (k & ~(1 << i) ) | (1 << pos);
       return k | (1 << pos);
    }
    
    ll dp(int cur,int f1,int f2,int f3,int k)
    {
       if (f[cur][f1][f2][f3][k] != -1)
        return f[cur][f1][f2][f3][k];
       ll &ans = f[cur][f1][f2][f3][k] = 0;
       if (cur == maxlen)
        {
           int len =  GetLength(k);
           if (len == tark)
            return ans = 1;
           else
            return ans = 0;
        }
       int st = f1?0:A[cur]-'0';
       int ed = f2?9:B[cur]-'0';
       for(int i = st ; i <= ed ; ++ i)
        {
          if (f3 && i == 0) //拥有前导零,这个不算上升的 
           ans += dp(cur+1, f1 | i > A[cur]-'0' , f2 | i < B[cur]-'0' , f3 & !i, 0 );  
          else
           ans += dp(cur+1, f1 | i > A[cur]-'0' , f2 | i < B[cur]-'0' , f3 & !i, tanxinset(k,i)  ); 
        }
       return ans;
    }
    
    
    int main(int argc,char *argv[])
    {
      std::ios::sync_with_stdio(false);
      std::cin.tie(0);
      int Case;
      cin >> Case;
      while(Case--)
       {
             cin >> A >> B >> tark;
             memset(f,-1,sizeof(f));
             maxlen = B.size();
             while(A.size() != maxlen)
              A = '0' + A;
             printf("%lld
    ",dp(0,0,0,1,0));
       }
      return 0;
    }
  • 相关阅读:
    Typescript---01 数据类型
    微信小程序开发01 --- 微信小程序项目结构介绍
    C# 高级编程05----常用修饰符
    C# 高级编程04----类
    C# 高级编程02----手动创建C#程序
    C# 高级编程03----细节内容
    C# 高级编程01----.Net基础介绍
    Docker----起步(2)----在Ubuntu上安装最新版的Docker CE
    Microsoft Graph API -----起题 Graph API
    Docker----与Asp.net core 的完美结合,在docker容器中创建Asp.Net Core 项目
  • 原文地址:https://www.cnblogs.com/Xiper/p/4539634.html
Copyright © 2020-2023  润新知