[hdu4352]XHXJ's LIS

考虑LIS的一种求法:维护每一个长度的最小结尾,此时这个序列只与每一个数字有没有出现有关,用2^10状压,状压+数位dp即可

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define ll long long
 4 int t,k,a[21];
 5 ll l,r,f[21][11][2005]; 
 6 int count(int k){ 
 7     int ans=0; 
 8     while (k){ 
 9         k&=k-1; 
10         ans++; 
11     }
12     return ans; 
13 }
14 ll dfs(int k,int t,int s,int p1,int p2){ 
15     if (!k)return count(s)==t; 
16     if ((p1)&&(p2)&&(f[k][t][s]>=0))return f[k][t][s]; 
17     int ma=9,la=-1,ss; 
18     ll ans=0; 
19     if (!p2)ma=a[k]; 
20     for(int i=9;i>ma;i--)
21         if (s&(1<<i))la=i; 
22     for(int i=ma;i>=0;i--){ 
23         if (s&(1<<i))la=i; 
24         ss=s;
25         if ((p1)||(i))ss+=(1<<i); 
26         if (la>=0)ss-=(1<<la); 
27         ans+=dfs(k-1,t,ss,p1|(i>0),p2|(i<ma)); 
28     }
29     if ((p1)&&(p2))f[k][t][s]=ans; 
30     return ans; 
31 }
32 ll calc(ll k,int p){ 
33     for(a[0]=0;k;k/=10)a[++a[0]]=k%10; 
34     return dfs(a[0],p,0,0,0); 
35 }
36 int main(){
37     scanf("%d",&t);
38     memset(f,-1,sizeof(f)); 
39     for(int ii=1;ii<=t;ii++){
40         scanf("%lld%lld%d",&l,&r,&k);
41         printf("Case #%d: %lld\n",ii,calc(r,k)-calc(l-1,k)); 
42     }
43 } 
View Code

 

posted @ 2019-08-09 13:42  PYWBKTDA  阅读(132)  评论(0编辑  收藏  举报