首页 > 代码库 > hdu 4352

hdu 4352

搞半天才懂

求区间L到R之间的数A满足A的的数位的最长递增序列的长度为K的数的个数。

s是各数字状态压缩后的

 

#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#include <cmath>#define maxn 205typedef long long ll;using namespace std;ll n,m,ans,tot,le,ri,k;ll dig[20],dp[20][1<<11][11];ll getstate(ll s,ll u,ll& xx)  // 状态转移{  ll i,ss;  for(i=u;i<10;i++)  {    if(s&(1<<i)) break ;  }  if(i<10)  {    ss=s^(1<<i);    ss=ss^(1<<u);  }  else  {    xx++;    ss=s^(1<<u);  }  return ss;}ll dfs(ll pos,ll s,ll len,ll flg,ll lead) // 当前位 LIS状态 LIS长度 上界标志 前导0标志{  if(pos==0)  {    if(len==k) return 1;    return 0;  }  if(!flg&&dp[pos][s][k]!=-1) return dp[pos][s][k];  ll i,j,t,ed,res=0;  if(flg) ed=dig[pos];  else ed=9;  for(i=0;i<=ed;i++)  {    ll ss,nlen=len;    if(lead==0&&i==0) ss=0;    else ss=getstate(s,i,nlen);    t=dfs(pos-1,ss,nlen,flg&&i==ed,lead||i!=0);    res+=t;  }  if(!flg) dp[pos][s][k]=res;  return res;}ll solve(ll x){  ll i,j,t=x;  tot=0;  while(t)  {    dig[++tot]=t%10;    t/=10;  }  ll res=dfs(tot,0,0,1,0);  return res;}int main(){  ll i,j,t,test=0;  memset(dp,-1,sizeof(dp));  scanf("%I64d",&t);  while(t--)  {    scanf("%I64d%I64d%I64d",&le,&ri,&k);    ans=solve(ri)-solve(le-1);    printf("Case #%I64d: %I64d\n",++test,ans);  }  return 0;}

 

hdu 4352