luogu1112 波浪数 题解

本文介绍了一种特殊类型的数字——多重波浪数,并提供了一种高效算法来寻找这些数字。多重波浪数是指在一个或多个不同进制下呈现出特定规律的数字。文章详细解释了如何通过编程手段解决这个问题。

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

Luogu1112 波浪数 转自www.luogu.org

题目描述

波浪数是在一对数字之间交替转换的数,如1212121,双重波浪数则是指在两种进制下都是波浪数的数,如十进制数191919是一个十进制下的波浪数,它对应的十一进制数121212也是一个波浪数,所以十进制数191919是一个双重波浪数。

类似的可以定义三重波浪数,三重波浪数在三种不同的进制中都是波浪数,甚至还有四重波浪数,如十进制300=606(七进制)=363(九进制)=454(八进制)=1A1(十三进制)…,你的任务就是在指定范围内找出双重、三重、四重波浪数。

输入输出格式

输入格式:

单独一行包含五个用空格隔开的十进制整数,前两个数表示进制的范围(2••32),第三与第四个数表示指定的范围(1••10000000),第五个数为2,3,4中的一个,表示要找的波浪数的重数。

输出格式:

从小到大以十进制形式输出指定范围内的指定重数的波浪数。一行输出一个数。

输入样例:

10 11 190000 960000 2

输出样例:

191919

383838

575757

767676

959595

 

 

题目大意:

    题目要求在规定范围内寻找多重波浪数。波浪数是用两位不同的数字间相互交替的数。x重波浪数就是一个数在其他的进制里有且仅有x个波浪数。

 

分析:

看到波浪数的每个部分以循环出现,就瞬间怂了,但是仔细看看,是每对数字循环出现,也就是说只有两个数字循环,这样我们就可以枚举每两个数,再枚举长度可以构造一个波浪数,再用hash的方法判断是几重波浪数。题目范围1~10000000,进制范围2~32如果每个数暴搜过去时间就至少是O(10^8)再加上判断各个进制波浪数的时间,肯定是要超时。这时就要预处理,找到这个范围内的进制最短的长度和最长的长度,在这里面枚举。效率就会大大增加。

 

代码:

#include <iostream>

#include <cstdio>

#include <cstring>

#include <cmath>

#include <bitset>

#include <ctime>

#include <set>

#include <sstream>

#include <vector>

#include <map>

#include <algorithm>

#include <queue>

using namespace std;

int a,b,R,L,cs;

long hash[10000005];

bool h[33][33][33][100];

long l(int jz,int s)

{

int sum=1;

while (s/jz)

{

s/=jz;

sum++;

}

return sum;

}

long bls(int jz,int length,int s1,int s2)

{

int num=s1;

for (int i=1;i<length;i++)

{

if (i%2) num=num*jz+s2;

else num=num*jz+s1;

}

return num;

}

/*

举例

A1A1(16)

1*1+10*16+1*16*16=1+160+256

1*16^0+A*16^1+1*16^2+A*16^3

=1*16^0+16^1*(A+1*16^1+A*16^2)

=1*16^0+16^1*(A+16^1*(1+A*16^1))

=1+16^1*(A+16^1*(1+A*16^1))

bls(jz,length,s1,s2)=s2+jz*(s1+jz*(s2+jz*()))

*/

void Solve(int jz)

{

int l1,l2;

l1=l(jz,L);l2=l(jz,R);

for (int i=l1;i<=l2;i++)

{

for (int j=1;j<jz;j++)

for (int k=0;k<jz;k++)

{

if (h[j][k][jz][i]||h[k][j][jz][i]||j==k) continue;

long number=bls(jz,i,j,k);

if (number>=L&&number<=R)

{

    hash[number]+=2;

    h[j][k][jz][i]=false;

h[k][j][jz][i]=false;

}

else if (number>R) break;//如果算第二位超过范围 接下来的就都超过范围了

}

}

}

void init ()

{

cin>>a>>b>>L>>R>>cs;

for (int i=a;i<=b;i++)

Solve(i);

}

int main()

{

init ();

for (int i=L;i<=R;i++) if (hash[i]==cs) cout<<i<<endl;;

return 0;

}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值