HDU4352 lis+状压+数位dp

来源:互联网 发布:桐乡淘宝美工 编辑:程序博客网 时间:2024/05/29 15:36

题干很智障,意思就是问从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;}
0 0
原创粉丝点击