H - K-th Nya Number (数位dp)

本文介绍了一种特定类型的数字——Nya数,并通过数位DP算法解决了一个有趣的问题:如何找出在给定范围内的第K个Nya数。该文详细解释了算法思路,并提供了完整的实现代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Arcueid likes nya number very much. 
A nya number is the number which has exactly X fours and Y sevens(If X=2 and Y=3 , 172441277 and 47770142 are nya numbers.But 14777 is not a nya number ,because it has only 1 four). 
Now, Arcueid wants to know the K-th nya number which is greater than P and not greater than Q. 
Input
The first line contains a positive integer T (T<=100), indicates there are T test cases. 
The second line contains 4 non-negative integers: P,Q,X and Y separated by spaces. 
( 0<=X+Y<=20 , 0< P<=Q <2^63) 
The third line contains an integer N(1<=N<=100). 
Then here comes N queries. 
Each of them contains an integer K_i (0<K_i <2^63).
Output
For each test case, display its case number and then print N lines. 
For each query, output a line contains an integer number, representing the K_i-th nya number in (P,Q]. 
If there is no such number,please output "Nya!"(without the quotes). 
Sample Input
1
38 400 1 1
10
1
2
3
4
5
6
7
8
9
10
Sample Output
Case #1:
47
74
147
174
247
274
347
374
Nya!
Nya!

给定X和Y的值,一个数字用十进制表示,对于数位4出现恰好X次,7恰好Y次的数字称为nya数。然后给P和Q, 后面是一系列查询, 每个查询K就是在区间(P,Q]上找到第K个nya数,不存在则输出Nya!

思路:

数位dp

代码:

#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;
typedef long long ll;
int t;
ll P,Q,X,Y;
int n;
int bit[20];
ll dp[20][20][20];
ll dfs(int len,int sta1,int st2,bool flag)
{
    if(sta1 > X || st2 > Y) return 0;

    if(len <= 0) return sta1 == X && st2 == Y;

    if(!flag && dp[len][sta1][st2] != -1)
        return dp[len][sta1][st2];
    int end = flag ? bit[len] : 9;
    ll res  = 0;
    for(int i=0;i<=end;i++)
    {
        if(i == 4)
        res += dfs(len-1,sta1+1,st2,flag && i == end);
        else if(i == 7)
        res += dfs(len-1,sta1,st2+1,flag && i == end);
        else
        res += dfs(len-1,sta1,st2,flag && i == end);
    }
    return flag ? res : dp[len][sta1][st2] = res;
}

ll cal(ll x)
{
    int pos= 0;
    while(x> 0)
    {
        bit[++pos] =x% 10;
        x/= 10;
    }
    return dfs(pos,0,0,1);
}
int main()
{
    int cas=1;
    scanf("%d",&t);
    while(t--)
    {
        printf("Case #%d:\n",cas++);
        memset(dp,-1,sizeof(dp));
        scanf("%I64d%I64d%I64d%I64d",&P,&Q,&X,&Y);
        ll dn=cal(P);
        ll up=cal(Q);
        scanf("%d",&n);
        while(n--)
        {
            ll m;
            scanf("%I64d",&m);
            ll l = P + 1;
            ll r = Q;
            if(m > up -dn)
            {
                printf("Nya!\n");
                continue;
            }
            while(l < r)
            {
                ll mid = (l + r) / 2;
                ll s=cal(mid);
                if(s - dn>= m )
                 r = mid;
                else
                l = mid + 1;
            }
            printf("%I64d\n",l);
        }

    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值