题目
题意
求[ L L L, R R R]里有多少数满足:十进制数位上的lis恰好等于 K K K
思路
首先这里lis需要模拟二分的过程。
然后把0是否出现,1是否出现…压缩成二进制状态,lis的时候就可以暴力插入某个值。
这里注意:不能每次都memset dp数组,每一个状态只能更新一次。(TLE)。
然后定义
d
p
[
i
]
[
j
]
[
k
]
[
z
]
:
dp[i][j][k][z]:
dp[i][j][k][z]:剩下
i
i
i位时,是否有上界限制(这一维可以省略),二进制状态为
k
k
k,lis为
z
z
z时的状态。
然后记忆化搜索,只有当没有上界限制的时候,可以return某一个dp值,这样复杂度也是线性ok的。
注意前导零和函数跳出进入的pos。
好题!好题!
/*
Author: Rshs
Time: 2019-11-09-21.28
*/
#include<bits/stdc++.h>
using namespace std;
#define FI first
#define SE second
#define LL long long
#define MP make_pair
#define PII pair<int,int>
#define SZ(a) (int)a.size()
const double pai = acos(-1);
const double eps = 1e-8;
const LL mod = 1e9+7;
const int MXN = 1e6+5;
LL L,R,K;
LL dp[25][2][(1<<10)][12];
vector<int>w;
int cc(int x){ //count weis
int re=0;
while(x) re=re+x%2,x/=2;
return re;
}
int change(int sta,int i){
for(int j=i;j<=9;j++){ // the first >= i
if(sta&(1<<j)) {sta-=(1<<j),sta+=(1<<i);return sta;}
}
return sta+=(1<<i);
}
LL dfs(int pos,int sta1,int sta2,int zz){//pos,is limit?,binaryString,leadingzero
if(pos==SZ(w)){
if(cc(sta2)==K) return 1;
else return 0;
}
//when it nolimit so can JiYiHuaDFS ,O(len)
if(dp[SZ(w)-pos][sta1][sta2][K]!=-1&&sta1==1) return dp[SZ(w)-pos][sta1][sta2][K];
LL re=0;
for(int i=0;i<=9;i++){
if(sta1==0&&i>w[pos]) continue;
int tsta2=change(sta2,i);
if(zz&&i==0) tsta2=0;//leading zero can't count
re=re+dfs(pos+1,(( i==w[pos] )&&( sta1==0 ))^1,tsta2,(zz==1)&&(i==0));
}
return dp[SZ(w)-pos][sta1][sta2][K]=re;
}
LL f(LL x){
LL tx=x;w.clear();
while(tx) w.push_back(tx%10),tx/=10;
if(x==0) w.push_back(0);
//while(SZ(w)<5)w.push_back(0);
reverse(w.begin(),w.end());
return dfs(0,0,0,1);
}
int MAIN(int avg){
scanf("%lld%lld%lld",&L,&R,&K);
//cout<<f(R)<<endl;
//cout<<f(L-1)<<endl;
printf("Case #%d: %lld\n",avg,f(R)-f(L-1));
return 0;
}
int main(){
memset(dp,-1,sizeof(dp));
int ca;cin>>ca;for(int i=1;i<=ca;i++) MAIN(i);
return 0;
}