【问题标题】:Circumference of Sierpinski triangle谢尔宾斯基三角形的周长
【发布时间】:2015-10-01 22:23:50
【问题描述】:

我目前正在为自己的练习做this problem。我设法通过了所有测试用例,所以我不知道出了什么问题。我的代码是:

#include <iomanip>
#include <iostream>
#include <vector>
#include <string>
#include <cmath>
using namespace std;
int main(){
   int num = 1;

   while(true){
    string line,stringRes;
    getline(cin,line);
    if(cin.eof()){break;}
    long double shrinks = atof(line.c_str());

    long double triangels = pow(3,shrinks);
    long double length = 3/pow(2,shrinks);
    long double res = floor(triangels* length * 3);
    int i = 0;
    while(res >= 10){
        i++;
        res =  res/10;
    };
    if(shrinks == 1){
        printf("Case %d: %d\n",num ,1);
    }else{
        printf("Case %d: %d\n",num ,i+1);
    }
    num++;
}
return 0;
}

例如,当我输入 1000 时,我得到 178,而 10000 我得到 1762。

输入样本

0
1
5
10
100

输出样本

Case 1: 1
Case 2: 1
Case 3: 2
Case 4: 3
Case 5: 19

对于每个案例,显示案例编号,后跟代表给定迭代次数的圆周整数部分所需的小数位数。遵循示例输出的格式。

【问题讨论】:

  • 标题中请仅使用英文字母。
  • 您能否添加有关预期输出是什么以及实际输出是什么的详细信息?
  • 我只是使用问题的名称。我链接了问题,但我会添加测试样本。

标签: c++ c++11 math c++14


【解决方案1】:

如前所述,您得到错误结果的原因是:使用 pow 会溢出,还因为您 - 正如您似乎已经意识到的那样 - 使用 3 作为起始边长。

这里有一个替代的、正确的解决方案,它有点短(没有溢出):

n &gt;= 0 阶谢尔宾斯基三角形的周长(或周长)P(n) 可以表示为:

P(n) = 3^(n + 1) / 2^n

我不提供证明,因为没有必要解决问题。但是,很容易理解必须是这种情况。一种方法是计算谢尔宾斯基三角形前几个阶的周长:39/227/481/8,...,另一种方法是考虑当你 (1 ) 将形状“缩小”½ 倍,(2) 将三角形“扩展”3 倍。

D(x) 的任意自然数(以 10 为底)x 的位数为:

D(x) = 1 + floor(log10(x))

所以计算序n的谢尔宾斯基周长的小数位数我们计算P(n) = 3^(n + 1) / 2^n的整数部分的位数,即D(floor(P(n))),这也是问题的解法:

D(floor(P(n))) = 1 + floor(log10(3^(n + 1) / 2^n)) = /log(a/b) = log(a) - log(b)/ =
= 1 + floor(log10(3^(n + 1)) - log10(2^n)) = /log10(a^b) = b * log10(a)/ =
= 1 + floor((n + 1) * log10(3) - n * log10(2))

解决问题的C++实现:

/** Calculates the number of digits in the integer part of the perimeter of the Sierpinski triangle of order n */
/** Author: Fredrik Präntare, Date: 19/3/2016 */
#include <iostream>
#include <algorithm> // log10, floor
using namespace std;

int main(){
    int c = 1, n;
    while(scanf("%d", &n) != EOF){
        int D_p = 1 + floor((n + 1) * log10(3) - n * log10(2));
        printf("Case %d: %d\n", c, D_p);
        c++;
    }
}

【讨论】:

  • 尽管这个问题才半岁多一点,但答案非常好。特别是考虑到您首先在数学上简化了问题。最后我有一点建议:对 log10 值使用静态常量。然后您可以进一步简化表达式:n * (log10_3 - log10_2) + log10_3。将log10_3 - log10_2 保存到另一个常量并删除log10_2 会进一步改善它!
  • 谢谢!这绝对是处理该表达式的正确和替代方法。 :-)
【解决方案2】:

您正在溢出triangels 的值。当你有

long double triangels = pow(3,shrinks);

shrinks = 10000 给出:1.6313501853426258743032567291812e+4771。

sizeof(long double) == 8 为 1.7E +/- 308 的 long double 的范围。

您很可能需要使用modular exponentiation 来解决此问题。

【讨论】:

  • 你有如何使用它的指南吗?
  • 我个人没有,但快速谷歌搜索给出了这个看起来不错的 SO 问题:stackoverflow.com/questions/2207006/…
  • 我不明白为什么当输入样本为 1 时输出样本为 1。因为在第 1 阶段,它的 9 + (1,5 *3) 为 13.5,所以整数部分为 2。
  • @user3664730 在第 0 次迭代中,我们的周长为 3,因为我们有 3 个 1 单位的边。在第 1 次迭代中,我们删除了中心三角形,它给了我们 3 个边为 0.5 的三角形,所以我们有 3*3*.5 或 4.5,可以用 1 个整数位表示。
  • 解决了问题!我读的文本好像每边都是 3 而不是 1。感谢您的帮助!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多