XHXJ's LIS [HDU 4352]

http://acm.hdu.edu.cn/showproblem.php?pid=4352

类似于O(nlog n)的LIS求法,用1<<10记录10以内数的出现情况,贪心更新。

View Code
//类似于O(nlog n)的LIS求法,用1<<10记录10以内数的出现情况,贪心更新。
const int MM = 11111;
typedef __int64 int64;
int K,cnt, num[MM];
int64 dp[20][1<<10][10],L,R;

void get_data() {
    scanf("%I64d%I64d%d",&L,&R,&K);
}
int getbit(int state) {
    int res=0;
    while(state) state-=lowbit(state),res++;
    return res;
}
int getchange(int x,int state) {
    for(int i=x;i<10;i++) {
        if(state&(1<<i)) return (state^(1<<i))|(1<<x);
    }
    return state|(1<<x);
}
int64 dfs(int le,int state,bool less,bool ok) { //ok前导0
    if(le==-1) return getbit(state)==K;
    if(!less && dp[le][state][K]!=-1) return dp[le][state][K]; 
    int64 res=0; int d, e=less?num[le]:9;
    for(d=0;d<=e;d++) {
        res+=dfs(le-1,state||d!=0?getchange(d,state):0,less&&d==e,ok||d!=0);
    }
    if(!less) dp[le][state][K]=res;
    return res;
}
int64 cal(int64 x) {
    for(cnt=0; x ;num[cnt++]=x%10,x/=10);
    return dfs(cnt-1,0,true,true);
}
void solve() {
    printcase();
    printf("%I64d\n",cal(R)-cal(L-1));
}

int main() {
    memset(dp,-1,sizeof(dp));
    int ca; scanf("%d",&ca);
    while(ca--) get_data(),solve();
    return 0;
}

 

posted @ 2013-05-03 09:53  zhang1107  阅读(131)  评论(0编辑  收藏  举报