原文:http://www.acmerblog.com/hdu-4352-xhxjs-lis-7363.html
* 问L到R,各位数字组成的严格上升子序列的长度为K的个数。 * 0<L<=R<263-1 and 1<=K<=10 * 注意这里最长上升子序列的定义,和LIS是一样的,不要求是连续的 * 所以用十位二进制表示0~9出现的情况,和O(nlogn)求LIS一样的方法进行更新
1 #include <algorithm> 2 #include <iostream> 3 #include <cstring> 4 #include <cstdlib> 5 #include <cstdio> 6 #include <vector> 7 #include <ctime> 8 #include <queue> 9 #include <list> 10 #include <set> 11 #include <map> 12 using namespace std; 13 #define INF 0x3f3f3f3f 14 typedef long long LL; 15 16 int bit[35]; 17 LL dp[35][15][1 << 10], k; 18 19 int GetNext(int st,int x) 20 { //刚开始用数组存,会超时啊(大哭),还是太嫩了 21 //找到第一个大于x的数并且替换他,nlogn求最长递增子序列的思想 22 for(int i=x;i<10;i++) 23 if(st&(1<<i)) return ((st^(1<<i))|(1<<x)); 24 return st|(1<<x); 25 } 26 int GetLen(int st) 27 { 28 int cnt=0; 29 while(st) 30 { 31 if(st&1) cnt++; 32 st>>=1; 33 } 34 return cnt; 35 } 36 LL dfs(int len, int length, int mark, int flag) 37 {//刚开始一直用dp[len][length][mark], 跟length没有毛线关系啊,wa了n发 38 if(len == 0) 39 return GetLen(mark) == k; 40 if(flag && dp[len][k][mark] >= 0) 41 return dp[len][k][mark]; 42 LL sum = 0; 43 int te = flag ? 9 : bit[len]; 44 for(int i = 0; i <= te; i++) 45 { 46 int Mark = ((length==0 && i==0) ? 0 : GetNext(mark, i)); 47 sum += dfs(len - 1, length || i , Mark, flag || (i < te)); 48 } 49 if(flag) 50 dp[len][k][mark] = sum; 51 return sum; 52 } 53 LL solve(LL n) 54 { 55 int len = 0; 56 while(n) 57 { 58 bit[++len] = n % 10; 59 n /= 10; 60 } 61 return dfs(len, 0, 0, 0); 62 } 63 int main() 64 { 65 int t; 66 LL l, r; 67 scanf("%d", &t); 68 memset(dp, -1, sizeof(dp)); 69 for(int i = 1; i <= t; i++) 70 { 71 cin >> l >> r >> k; 72 cout << "Case #"<< i << ": "; 73 cout << solve(r) - solve(l - 1) << endl; 74 } 75 return 0; 76 }