問題の意味
デジタルは、シークの数の範囲内で最も長いシーケンス桁区間k上昇します
説明
最初のいくつかのDPのアイデアによって導入された、DP伝達方程式:
(POS、...ステータス)DFSが累積DFS(POS-1、.stautselse ...)=
DPとしてDPアレイ缶メモレコード[POS] [ステータス] [ k]を、 メモkの理由は、kは、異なるアクセス満たすためである
0が存在しないことを表し、私の存在に対応するビットの数を表す二進数で圧縮された状態に、ステータスレコードが選択された位置posに数字のデジタル組み合わせの始まりです。
Stautusの方法は等価的LIS得られる、注目は、特定のアクセス・ビットの存在に正確ではないかもしれない、と等価であるが、最も長い配列の長さは変化しない上昇です。
これにより最後の数字は、いくつかの方法の結果は、上昇サブシーケンスの最長数の長さをkに等しいかどうか、数がここ-1位置決定決定DP除去なるれます。問題は、x = 0の使用を考慮することがないので、それを行うために他のデジタルDP通常の方法によれば、0をリードし、LICアルゴリズムに気づく、結果も大きく、最も長いサブシーケンス+1結果が得られ、1ビット0に登場します。
#include <cstdio>
#include <cstring>
#define ll long long
using namespace std;
int k;
int dig[25];
ll dp[25][1<<10][11];
int changes(int s, int x){
for(int i = x; i < 10; i++){
if(s&(1<<i))
return (s^(1<<i))|(1<<x);
}
return s|(1<<x);
}
int getnum(int s){
int ans = 0;
while(s){
if(s&1)
ans++;
s>>=1;
}
return ans;
}
ll dfs(int pos,int sta, int limit, int pre){
if(pos == -1) return getnum(sta) == k;
if(!limit && dp[pos][sta][k]!= -1) return dp[pos][sta][k];
int top = limit? dig[pos]:9;
ll ans = 0;
for(int i = 0; i <= top; i++){
ans += dfs(pos-1, (pre&&(i == 0))?0:changes(sta, i),limit&&(i == top), pre&&(i == 0));
}
if(!limit) dp[pos][sta][k] = ans;
return ans;
}
ll slove(ll x){
int pos = 0;
while(x){
dig[pos++] = x%10;
x /= 10;
}
ll ans = dfs(pos-1,0,1,1);
return ans;
}
int main(){
int t;
ll n, m;
memset(dp, -1, sizeof(dp));
scanf("%d", &t);
int cont = 1;
while(t--){
scanf("%lld %lld %d", &n, &m, &k);
printf("Case #%d: %lld\n", cont++, slove(m) - slove(n-1));
}
return 0;
}