【HDU】4352 XHXJ's LIS(数位dp+状压)

题目

传送门:QWQ

分析

数位dp

状压一下现在的$ O(nlogn) $的$ LIS $的二分数组

数据小,所以更新时直接暴力不用二分了。

代码

#include <bits/stdc++.h>
using namespace std;
typedef  long long ll;
const int maxn=20;
ll dp[maxn][1<<11][12];int k,digit[maxn];
int nextstate(int state,int x){
    for(int i=x;i<10;i++){
        if(state&(1<<i)){
            state^=(1<<i); break;
        }
    }
    return (state|(1<<x));
}
int getnum(int x){
    int ans=0;
    while(x){
        if(x&1) ans++;
        x>>=1;
    }
    return ans;
}
ll dfs(int pos,int state,int leadingzero,int border){
    if(pos==0) return getnum(state)==k;    
    if(!leadingzero && !border && dp[pos][state][k]!=-1) return dp[pos][state][k];
    ll ans=0;
    int end=border?digit[pos]:9;
    for(int i=0;i<=end;i++){
        if(i==0 && leadingzero) ans+=dfs(pos-1,state,1,border&&i==end);
        else ans+=dfs(pos-1,nextstate(state,i),0,border&&i==end);
    }
    if(!leadingzero&&!border) dp[pos][state][k]=ans;
    return ans;
}
ll cal(ll n){
    int pos=0;
    while(n){
        digit[++pos]=n%10; n/=10;
    }
    return dfs(pos,0,1,1);
}
int main(){
    int t;ll l,r; cin>>t;
    memset(dp,-1,sizeof(dp));
    for(int i=1;i<=t;i++){
        cin>>l>>r>>k;
        cout<<"Case #"<<i<<": "<<cal(r)-cal(l-1)<<endl;
    }
    return 0;
}
/*
100
1234567 123456789012 8
5678567890101 1234567890123456 9
*/

猜你喜欢

转载自www.cnblogs.com/noblex/p/9363589.html