题干很智障,意思就是问从l到r里lis为k的数有几个
首先从0到9一共十个数,那么最长不能超过10
dp数组开一个状态,位数,k这样的三维就够
状态是状态压缩的状态
你可以用状态压缩来表达lis的数组
有点取巧了,我看别人的题解都是两维,lis部分用的nlgn方法
我第一次看见tle以后直接开了第三维记录了k爆草过去了…
因为早就料到他的测试样例里肯定有重复的和k超过10的
你看他的T有一万这么大不重复就怪了
所以特判了k超过十的直接返回0
然后dp数组本身只需要初始化一次…下次k只要一样的就能用上一轮的结果
回头再写下nlgn的
T(T<=10000)0
#include<iostream>
#include<algorithm>
#include<string>
#include<memory.h>
using namespace std;
int bte[100];
long long k;
long long dp[1<<12][20][10];
long long chai(long long n)
{
int js = 0;
while (n)
{
if (n & 1)js++;
n >>= 1;
}
return js;
}
long long dfs(int weishu, int biaoji, long long zhuangtai,int qd)
{
int as = chai(zhuangtai);
if (weishu == 0)
{
if (as== k)return 1;
return 0;
}
if (biaoji&&dp[zhuangtai][weishu][k] != -1)return dp[zhuangtai][weishu][k];
int bianjie = biaoji ? 9 : bte[weishu];
long long sum = 0;
for (int a = 0;a <= bianjie;a++)
{
if (a == 0&&qd==0)sum += dfs(weishu - 1, !(biaoji == 0 && a == bianjie&&bianjie == bte[weishu]), zhuangtai,qd);
else
{
long long cs = 1 << (a);
if(cs&zhuangtai)sum+= dfs(weishu - 1, !(biaoji == 0 && a == bianjie&&bianjie == bte[weishu]), zhuangtai,1);
else
{
long long xjt = zhuangtai;
xjt +=cs;
for (int b = a+1;b <= 9;b++)
{
long long cc = 1 << (b);
if (cc&xjt)
{
xjt -= cc;
break;
}
}
sum += dfs(weishu - 1, !(biaoji == 0 && a == bianjie&&bianjie == bte[weishu]), xjt,1);
}
}
}
if (biaoji)dp[zhuangtai][weishu][k] = sum;
return sum;
}
long long jieju(long long n)
{
if (k > 10)return 0;
memset(bte, 0, sizeof(bte));
if (n <= 0)return 0;
long long q = n;
while (q)
{
bte[++bte[0]] = q % 10;
q /= 10;
}
return dfs(bte[0], 0, 0,0);
}
int main()
{
#define int long long
int T;
cin >> T;
int u = 0;
memset(dp, -1, sizeof(dp));
while (T--)
{
int n, m;
cin >> n >> m >> k;
int yu = jieju(m) - jieju(n - 1);
printf("Case #%lld: %lld\n", ++u,yu);
}
return 0;
}