动态点分治

题目描述

CJK 是一个喜欢数据结构的同学。一天他看到 BZOJ 4012 这一题。“这似乎可以用动态点分治做。”,他想。然而他并不会动态点分治,因此他拿着这一题去问 XXX。 然而 XXX 跟他说:“你呀,毕竟图样图森破,上台拿衣服!连基础都没学好,就想学这些高端的东西!来,我这里有一题,如果你能把这道题秒掉,我才能教你动态点分治!” 于是 CJK 打开题目。题目很短,只有一句话: “给出 l, r, k,请从小到大输出所有在 [l, r] 范围内,能表示为 k 的非负整数次方的所有数。” “多组数据。”,XXX 补充说,“注意所有数的 0 次方都为 1,因此 1 也得算进去哦。”

输入描述:

第一行一个数 T,表示数据组数。接下来 T 行,每行 3 个数 l,r,k,表示一组数据。

输出描述:

对于每一组数据输出一行(总共输出 T 行)。如果存在符合要求的数,则在一行内从小到大输出这些数;否则输出一个字符串 “None.”(包括句点,不包括引号)。

示例1

输入

4
1 10 2
2 4 5
19562 31702689720 17701
3680 37745933600 10

输出

1 2 4 8
None.
313325401
10000 100000 1000000 10000000 100000000 1000000000 10000000000

备注:

对于所有数据,T ≤ 10000,l ≤ r,0≤ l,r,k < 263。子任务 1(20 分):r - l ≤ 1000。子任务 2(30 分):l, r, k < 231。子任务 3(50 分):l, r, k < 263。这里的子任务表示的是数据类型,并不捆绑测试。三个子任务中,各有 10 分的数据,满足 T = 10 且数据是随机的。特别注意:本题中 0 的 0 次方也看做 1。

思路:

求出现在[ ?,? ]内的形如 k i k^i ki 的数
模拟题意就好了,注意一下 ? = 1 或 ? = 0 的边界
坑点:有可能 ? ≤ ?,但是 ?? 溢出了,溢出之后刚好又在[ ?,? ]甚至[ ?,? ]之间应对措施:如果 ? > r k \frac{r}{k} kr,则 break

代码:

#include<bits/stdc++.h>
#define int __int128
inline int read()
{
    int res=0;
    char ch;
    while((ch=getchar())<'0'||ch>'9');
    for(;ch>='0'&&ch<='9';ch=getchar())
        res=res*10+ch-'0';
    return res;
}
inline void write(int x)
{
    if(x>=10)
        write(x/10);
    putchar(x%10+'0');
    return;
}
inline void solve()
{
    int l,r,k;
    bool flag=0;
    register int i;
    l=read();r=read();k=read();
    if(k==0)
    {
        if(l<=0&&r>=0)
            putchar('0'),putchar(' '),flag=1;
        if(l<=1&&r>=1)
            putchar('1'),putchar(' '),flag=1;
        if(!flag)
            puts("None.");
        else
            putchar('\n');
        return;
    }
    if(k==1)
    {
        if(l<=1&&r>=1)
                    putchar('1'),putchar(' '),flag=1;
        if(!flag)
            puts("None.");
        else
            putchar('\n');
        return;
    }
    for(i=1;i<=r;i*=k)
        if(i>=l)
            write(i),putchar(' '),flag=1;
    if(!flag)
        puts("None.");
    else
        putchar('\n');
    return;
}
signed main()
{
    int T;
    T=read();
    while(T--)
        solve();
    return 0;
}

来源:nkw

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值