Algorithm 如何生成只包含两种数字类型的第n个数字?

Algorithm 如何生成只包含两种数字类型的第n个数字?,algorithm,c++11,Algorithm,C++11,我们将特殊编号定义为仅包含4s和7s的编号 让我们看看例子:447、477、444和777是特殊数字,而407不是 我需要帮助了解生成第n个特殊编号的n的法律/规则是什么 我尝试了下面的代码,但没有成功 int x[2000]; int k=0; void dfs( int a ) { if(k==1021) return; x[k++]=a; dfs(a*10+4); dfs(a*10+7); } dfs(4); dfs(7); 关于如何做到这一点,有什么解决方案

我们将特殊编号定义为仅包含4s和7s的编号

让我们看看例子:
447
477
444
777
特殊数字,而
407
不是

我需要帮助了解生成第n个特殊编号的
n的法律/规则是什么

我尝试了下面的代码,但没有成功

int x[2000];
int k=0;

void dfs( int a ) {
  if(k==1021)
    return;
  x[k++]=a;
  dfs(a*10+4);
  dfs(a*10+7);
}

dfs(4);
dfs(7);

关于如何做到这一点,有什么解决方案或想法吗

显而易见的答案:测试7和4:

bool check (unsigned int number) {
    if(number == 0)
        return false;
    while(number != 0) {
        unsigned int digit = number % 10;
        if( digit != 4 && digit != 7 )
            return false;
        number /= 10; // integer division, ie. "rounding down"
    }
    return true;
}

int main(int argc, char **argv) {
    for(int number = 0; number <= 100; number ++) {
        if(check(number)) 
             do_what_ever_you_want(number);
    }
    return 0;
}
bool检查(无符号整数){
如果(数字==0)
返回false;
while(数字!=0){
无符号整数位数=数字%10;
如果(数字!=4和数字!=7)
返回false;
数字/=10;//整数除法,即“向下舍入”
}
返回true;
}
int main(int argc,字符**argv){

用于(int number=0;number为什么您的代码被破坏

您的代码不起作用,因为您的终止条件取决于一个全局变量
k
,该变量在第二次调用
dfs(7)
之前不会重置。因此,此调用终止时不会生成任何新的特殊号码。因此,最终您将错过所有以
7
开头的特殊号码

您可以通过调用:
dfs(0)
并放弃您
x
数组的第一个条目来修复此问题。但是整个程序编写得很糟糕。依赖函数中的全局变量是对灾难的调用

生成所有特殊编号的算法

如果数字介于0和100之间,则它有0、1或2位数字

所以基本上所有的特殊数字都是:4,7,44,47,74,77

如果要扩展到数字
d
,则可以使用二进制数
d
位。选择值为
0
的位将是十进制数字
4
,值为
1
的位将转换为十进制数字
7
。然后通过枚举
0
2^d-1
您可以生成所有特殊编号

在上一个案例中,我们列举了所有特殊编号,包括:

  • 1位,转换为2个特殊数字:
    4
    ad
    7
  • 2位,翻译成4个特殊数字:
    44
    47
    74
    77
如何获取第n个特殊号码 首先,我们考虑一个基于1的索引。 您只需注意,二进制表示小于
d
位的特殊数的计数是:
2^1+2^2+…+2^d=2(2^d-1)=2^(d+1)-2

您可以执行一个简单的循环递增
d
直到
2^(d+1)-2
并不是严格低于
n
。这告诉您应该对
n
使用
d
位二进制表示。您可以将
2^d-2
减为
n
,并将
1
减为
1,因为我们使用基于
1
的索引。现在,最终的数字可以通过上述步骤传递到整数这是一个特殊的号码

示例:第五特殊编号

2^2-2 = 2 <  5   => d+1 > 2
2^3-2 = 6 >= 5   => d+1 = 3  => d = 2

n-2^d+2-1 = 5-4+2-1 = 2 = 10b (using 2 bits as d = 2)

=> 5th special number is: 74
2^2-2=2<5=>d+1>2
2^3-2=6>=5=>d+1=3=>d=2
n-2^d+2-1=5-4+2-1=2=10b(使用2位作为d=2)
=>第五个特殊号码是:74

为此,我们可以使用二进制。因为7>4,所以将4s称为0s,将7s称为1s。假设我们正在寻找第n个特殊数字。将k定义为第n个特殊数字的数字更少的特殊数字。现在,我们来看看如何使用二进制。假设我们知道第10个特殊数字有3个数字,并且k=6。我们正在寻找10-6=三位数特殊编号列表中的第四个编号

4
-
0
77
-
11

7
-
1
444
-
000

44
-
00
447
-
001

47
-
01
474
-
010

74
-
10
477
-
011
>i)%2)==1; 答案+=(is7-7:4)*功率(10,i); } 返回答案; }

这些数字很快就变大了,所以如果你想找大的
n
并且不想出现负数,你可以简单地将数字保存在数组中而不是整数,然后按顺序打印出来。

我试着按照你的想法来回答这个问题。 也许有人会从中得到帮助

int x[2000];
int k = 0;
const int num_len = 8;

void dfs(int a, int level)
{
    if (level > num_len)
        return;
    x[k++] = a;
    dfs(a * 10 + 4, level + 1);
    dfs(a * 10 + 7, level + 1);
}

int main()
{
    memset(x, 0, sizeof(x));
    dfs(0, 0);
    sort(x, x+k);

    int nth;
    cin >> nth;
    cout << x[nth] << endl;
    return 0;
}
intx[2000];
int k=0;
常数int num_len=8;
无效dfs(整数a,整数级别)
{
如果(级别>数量)
返回;
x[k++]=a;
dfs(a*10+4,级别+1);
dfs(a*10+7,级别+1);
}
int main()
{
memset(x,0,sizeof(x));
dfs(0,0);
排序(x,x+k);
int n;
cin>>n;

CUT你确定你在使用C++吗?看起来像C。它们在语法上非常相似。你以前试过C++吗?是的,我是一个狂热的C++程序员,这就是我为什么要问的,这是有效的,迂腐的,C。你的代码不是惯用的C++,因此是合法的问题。你甚至理解我的问题题目吗?也许不是,但是老实说,我很好。在英语中,如果我不懂,恐怕你应该重新措辞。谢谢,但我知道。我需要的是生成0到10^100的规则example@Meyer请参阅我的更新。对于10^100,您需要输出超过2^100个特殊数字,我怀疑这是否可行。@Meyer,说真的,不要在评论中提出新问题。@Meyer你说“谢谢,但我知道。”,但你似乎一点也不了解fjardon的想法。顺便说一句,我可以用更好的代码检查,但我需要的不是检查,而是我需要生成特殊代码的想法numbers@Meyer哦,我想我明白了,你需要一个函数来生成第n个特殊数(通过实际生成,而不是直到第n个才计数)?@Meyer
int x[2000];
int k = 0;
const int num_len = 8;

void dfs(int a, int level)
{
    if (level > num_len)
        return;
    x[k++] = a;
    dfs(a * 10 + 4, level + 1);
    dfs(a * 10 + 7, level + 1);
}

int main()
{
    memset(x, 0, sizeof(x));
    dfs(0, 0);
    sort(x, x+k);

    int nth;
    cin >> nth;
    cout << x[nth] << endl;
    return 0;
}