XHXJ's LIS (数位dp,bitset状态压缩)

题目链接
题目大意:给出L和R找出在[L,R]中满足最长递增子序列长度等于K的个数。
思路:
本来想的是维护一个num[10],num[i]表示以i结尾的lis的长度,0<=num[i]<=9。然后状态压缩的时候发现压缩后太大,看了题解之后知道,必须要用nlogn求lis的思路来做,因为nlogn的思路是维护一个长度为10的bool数组,压缩后状态数少很多。

#include 
#define ll long long
using namespace std;
int dp[20][1300][20];
int len;
int dig[20];
const int mod = 1e9+7;
int get_next(int state,int x){
    bitset<10>bit = state;
    int i;
    for(i = x;i <= 9;i ++){
        if(bit[i]==1) break;
    }
    if(i!=10) bit[i] = 0;
    bit[x] = 1;
    int ans  = bit.to_ulong();
    return ans;
}
bool check(int state,int k){
    bitset<10>bit = state;
    if(bit.count()==k) return 1;
    else return 0;
}
ll dfs(int pos,int state,int k,bool zero,bool limit){
    if(pos==0) return check(state,k);
    if(!limit&&dp[pos][state][k]!=-1&&!zero) return dp[pos][state][k];
    int i;
    int up = limit?dig[pos]:9;
    ll ans=0;
    for(i = 0;i <= up;i ++){
        if(zero&&i==0){
            ans += dfs(pos-1,state,k,zero&&i==0,limit&&i==up);
            continue;
        }
        int next = get_next(state,i);
        ans += dfs(pos-1,next,k,zero&&i==0,limit&&i==up);
    }
    if(!limit&&!zero)dp[pos][state][k] = ans;
    return ans;
}
ll solve(ll n,int k){
    if(n==-1) return 0;
    len = 0;
    while(n!=0){
        dig[++len] = n%10;
        n /= 10;
    }
    return dfs(len,0,k,1,1);
}
int main()
{
    freopen("a.txt","r",stdin);
    ios::sync_with_stdio(0);
    int T;
    cin>>T;
    memset(dp,-1,sizeof(dp));
    int tot = 0;
    while(T--){
        tot ++;
        ll l,r;
        int k;
        cin>>l>>r>>k;
        cout<<"Case #"<": ";
        cout<1,k)<return 0;
}

你可能感兴趣的:(数位dp)