为在[L, R]区间中, 组成数字严格上升并且长度为K的个数
主要是状态的变化,
这里用了状态压缩来压缩一个10位数, 对于1356 长度不变的情况下如果要插入4,更具O(nlgn)
的LIS算法,会更新成1346, 是找到里面 a[i] > 4的第一个数,把他从原状态中去掉(s ^ (1 << i)) 再把x = 4 加上的情况 s‘ | (1 <<x)
/***********************************************
* Author: fisty
* Created Time: 2015/6/18 16:56:17
* File Name : hdu4352.cpp
*********************************************** */
#include <iostream>
#include <cstring>
#include <deque>
#include <cmath>
#include <queue>
#include <stack>
#include <list>
#include <map>
#include <set>
#include <string>
#include <vector>
#include <cstdio>
#include <bitset>
#include <algorithm>
using namespace std;
#define Debug(x) cout << #x << " " << x <<endl
#define Memset(x, a) memset(x, a, sizeof(x))
const int INF = 0x3f3f3f3f;
typedef long long LL;
typedef pair<int, int> P;
#define FOR(i, a, b) for(int i = a;i < b; i++)
#define MAX_N 21
int t;
LL L, R, K;
int digit[MAX_N];
LL f[MAX_N][1<<10][MAX_N];
int getcount(int x){
int sum = 0;
while(x){
if(x & 1) sum++;
x >>= 1;
}
return sum;
}
int getnew(int x, int s){
for(int i = x;i < 10; i++){
//寻找s中比x 大的第一个数 i
if(s & (1<<i)){
//如果找到,先在s中去掉这个数,再把 x 加上
return (s ^ (1<<i)) | (1 << x);
}
}
return s | (1 << x); //没有找到比x大的数,直接把x加上
}
LL dfs(int len, int s, int e, int zero){
if(len < 0) return getcount(s) == K;
if(!e && f[len][s][K] != -1) return f[len][s][K];
LL ans = 0;
int u = e ? digit[len] : 9;
for(int d = 0; d <= u; d++){
int z = zero && (d == 0);
ans += dfs(len-1, z ? 0 : getnew(d, s), e && (d == u), z);
}
if(!e) f[len][s][K] = ans;
return ans;
}
LL solve(LL x){
int len = 0;
while(x){
digit[len++] = x % 10;
x /= 10;
}
return dfs(len-1, 0, 1, 1);
}
int main(){
//freopen("in.cpp", "r", stdin);
cin.tie(0);
ios::sync_with_stdio(false);
cin >> t;
int cnt = 1;
Memset(f, -1);
while(t--){
cin >> L >> R >> K;
cout << "Case" << " #" << cnt++ << ": ";
cout << solve(R) - solve(L-1) << endl;
}
return 0;
}