P1112 波浪数

我理解的题目意思

波浪数是在一对不同数字之间交替转换的数,双重波浪数则是指在两种进制下都是波浪数的数。特别地,只有一位的数也算作波浪数,例如 1。

输入单独一行包含五个用空格隔开的十进制整数 l,r,L,R,k。[l,r] 表示应当考虑的进制的范围,[L,R] 表示应当考虑的数字的范围,k 表示你应该找的波浪数的重数。

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

$$2≤l≤r≤32,1≤L≤R≤10^7,k∈{2,3,4}。$$

解题思路

最暴力的方法肯定是遍历[L,R]的每个数进行[l,r]进制的波浪数检查,然后输出符合需要重数的数。但这样大概率会超时,而且不美观,肯定有更聪明的解法。

我不找数,让数来找我,构造符合[l,r]进制的波浪数,维护一个数组来记录数的波浪数重数,最后顺序输出就可以了。怎么构造呢,枚举两个不同的k进制数i、j,使得在数中i、j交替出现,设置一个标志用于判断何时应该放i何时放j。细节:i从1开始枚举,j从0开始枚举,先在数中放i。

代码:

#include <iostream>

using namespace std;

int v[10000005];
int m, n, l, r, c;

int main()
{
    cin >> m >> n >> l >> r >> c;
    for (int k = m; k <= n; k++)
    {
        for (int i = 1; i < k; i++)
            for (int j = 0; j < k; j++)
            {
                if (i != j)
                {
                    int x = 0, t = 0;
                    while (x <= r)
                    {
                        if (t % 2 == 0)
                        {
                            x = x * k + i;
                            t++;
                        }
                        else
                        {
                            x = x * k + j;
                            t++;
                        }
                        if (x >= l && x <= r)
                        {
                            v[x]++;
                        }
                    }
                }
            }
    }
    for (int i = l; i <= r; i++)
    {
        if (v[i] == c)
            cout << i << endl;
    }
    return 0;
}