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

    题目大意:让你求l到r 之间数位的最长上升子序列的个数为k 的数的数量。

    思路:用状态压缩模拟求最长上升子序列的过程,因为最多不超过10个所以可以压缩, 用dp[ i ][ j ][ k ]表示数位为i,最长上升子序列的状态为j,

    最后最长上升序列为k的方案数。

    #include<bits/stdc++.h>
    #define ll long long
    using namespace std;
    ll f[20][1<<11][11];
    ll dig[20],tot,k;
    ll cal(ll s,ll u,ll &len)
    {
        ll i;
        for(i=u;i<10;i++)
            if(s&(1<<i)) break;
        if(i<10)
        {
            s^=(1<<i);
            s^=(1<<u);
        }
        else s^=(1<<u),len++;
        return s;
    }
    ll dp(ll pos,ll s,ll len,bool limit,bool lead)
    {
        if(pos==-1)
            return len==k;
        if(!limit && f[pos][s][k]!=-1)
            return f[pos][s][k];
        ll up=limit? dig[pos]:9;
        ll ans=0;
        for(ll i=0;i<=up;i++)
        {
            ll nx_s,nx_len=len;
            if(lead && i==0) nx_s=0;
            else nx_s=cal(s,i,nx_len);
            ans+=dp(pos-1,nx_s,nx_len,limit && i==up,lead && i==0);
        }
        if(!limit) f[pos][s][k]=ans;
        return ans;
    
    }
    ll solve(ll x)
    {
        tot=0;
        while(x)
        {
            dig[tot++]=x%10;
            x/=10;
        }
        return dp(tot-1,0,0,true,1);
    }
    int main()
    {
        memset(f,-1,sizeof(f));
        ll T; scanf("%I64d",&T);
        for(ll cas=1;cas<=T;cas++)
        {
            ll l,r; scanf("%I64d%I64d%I64d",&l,&r,&k);
            ll ans1=solve(r);
            ll ans2=solve(l-1);
            printf("Case #%I64d: %I64d
    ",cas,ans1-ans2);
        }
        return 0;
    }
  • 相关阅读:
    PAT Basic Level 1013
    PAT Basic Level 1012
    PAT Basic Level 1011
    PAT Basic Level 1009
    PAT Basic Level 1010
    PAT Basic Level 1008 *
    PAT Basic Level 1007 *
    .NET Entity Framework入门简介及简单操作
    SQL Server 查询处理中的各个阶段(SQL执行顺序)
    泛型优点和特性
  • 原文地址:https://www.cnblogs.com/CJLHY/p/8391978.html
Copyright © 2011-2022 走看看