zcmu1781

1781: 上升序列数

Time Limit: 1 Sec   Memory Limit: 128 MB
Submit: 8   Solved: 3
[ Submit][ Status][ Web Board]

Description

假设有一个数列1,4,5,6,6,7那么这个数列的严格上升子序列就是1,4,5,6,7。现在有一个数比如123,如果单独看123的每一位就是1,2,3,
那么我们就能得到长度是3的(1,2,3)的严格上升子序列。假设一个数的最长的严格上升子序列长度是k,那么这个数就是k魅力数,现在我需
要计算区间[L,R]中有几个k魅力数?

Input

一个T(T<=10000),接下来T行,每行三个数L,R,K(0<L<=R<2^63.1<=K<=10)

Output

Case #x: y,x是测试编号从1开始,y表示答案

Sample Input

1123 321 2

Sample Output

Case #1: 139

当时校赛的时候看到这题的时候内心小小的激动了一下 因为这题在杭电(hdu4352)上看到过 不过遗憾的是这题紧紧看过因为

能力有限所以当时没有动手写 虽然校赛的时候还是不知道怎么写 不过后来看了大佬们的题解就知道了要用到nlogn

的上升子序列算法因为数字只有10个,我们可以状态压缩 因为数字只有10个所以用状态压缩

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<cstdio>
#include<string>
#include<set>
#include<map>
#include<queue>
#include<vector>
#include<stack>
using namespace std;
#define LL long long
#define cl(a,b) memset(a,b,sizeof(a))
#define MAXN 7
#define pi acos(-1)
LL dp[25][1<<10][11];//i为当前进行到的数位,j状态压缩,为10个数字出现过的,其中1的个数就是最长上升子序列,k要求的上升子序列的长度
int bit[200];
LL k;
int nloglis(int x,int s)
{
    for(int i=x;i<10;i++)
        if(s&(1<<i))return(s^(1<<i))|(1<<x);
    return s|(1<<x);
}
int calnum(int n)
{
    int l=0;
    while(n)
    {
        if(n&1)l++;
        n>>=1;
    }
    return l;
}
LL dfs(int pos,int num,int flag,int zero)
{
    if(pos==-1)return calnum(num)==k;
    if(!flag&&dp[pos][num][k]!=-1)return dp[pos][num][k];
    LL ans=0;
    int s=flag?bit[pos]:9;
    for(int i=0;i<=s;i++)
    {
        int num1;
        if(zero&&!i)num1=0;
        else num1=nloglis(i,num);
        ans+=dfs(pos-1,num1,flag&&i==s,zero&&!i);
    }
    if(!flag)dp[pos][num][k]=ans;
    return ans;
}
LL solve(LL n)
{
    int l=0;
    while(n)
    {
        bit[l++]=n%10;
        n/=10;
    }
    return dfs(l-1,0,1,1);
}
int main()
{
    int t,test=0;
    LL l,r;
    cl(dp,-1);
    scanf("%d",&t);
    while(t--)
    {
        scanf("%lld%lld%lld",&l,&r,&k);
        printf("Case #%d: %lld\n",++test,solve(r)-solve(l-1));
    }
    return 0;
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值