标签:
搞半天才懂
求区间L到R之间的数A满足A的的数位的最长递增序列的长度为K的数的个数。
s是各数字状态压缩后的
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #define maxn 205 typedef 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; }
标签:
原文地址:http://www.cnblogs.com/cnblogs321114287/p/4265368.html