算法,找到"数字不除以平方数"在给定的最小值和最大值之间

时间:2018-03-30 05:44:27

标签: c++ algorithm primes

  

问题

     

最小值min和max value max,找到所有   数字未除以"平方数"在最小和最大之间(1< = min< = 1trilion,max-min< = 1,000,000)

     

实施例

     

min为1,max为10.

     

答案是1,2,3,5,6,7,10中的7,因为4,8除以平方数   2 ^ 2 = 4。

我的方法。

  1. 所有数字除以平方数也除以平方素数。

  2. 使用eratosthenes的seive,计算小于sqrt(max)的所有平方素数

  3. 查找所有数字除以上面的suqare素数。

  4. 但我得到了#34;时间限制"或"错误"从该网站。我该如何证明?下面是代码。

    void Eratos()
    {
        for (ll i = 2; i <= primeMax; i++) num[i] = i;
    
        for (ll i = 2; i <= 100; i++) {
            for (ll j = 2; j <= primeMax; j++) {
                if (num[j] == -1) continue;
                else if (num[j] > i && num[j] % i == 0) num[j] = -1;
            }
        }
    
        for (ll i = 2, j = 0; i <= primeMax; i++) if (num[i] != -1) {
            prime[j] = num[i]*num[i];
            j++;
        }
    }
    

2 个答案:

答案 0 :(得分:4)

您正在检查所有素数(np)范围内的所有数字(nr = max-min),因此复杂度为Sum (nr / (sq[0]) + nr / (sq[1]) +...nr / (sq[np-1])

但你可以制作素数列表并在min..max范围内再次使用Eratosthenes筛选方法,标记平方数。所以代码会有关于

O(np + nr)

关于((min + psq - 1) div psq) * psq

的复杂性(可能)

例如,范围是50 ... 80。 Prime square list是4,9,25,49。使用31个条目创建布尔或位数组。首次运行标记条目52,56,60..80。第二轮:54,63,72;第三次运行标记50,75,第四次标记没有。现在没有标记的条目51,53,55..79就是您所需要的。

范围中的第一个条目,可被某个平方psq整除

function CountSquareless(AMin, AMax: Int64): Integer;

var
  PrSqList: TList<Int64>;

procedure MakePrimeList; //Eratosphenes sieve
var
  num: array of Byte;
  i, j: Integer;
begin
  SetLength(num, 1000001);
  PrSqList := TList<Int64>.Create;
  for i := 2 to 1000000 div 2 do
    for j := 2 to (1000000 div i) do
       num[i * j] := 1;
  for i := 2 to 1000000 do
    if num[i] = 0 then
       PrSqList.Add(Int64(i) * i);
end;

var
  num: array of Byte;
  i, nr: Integer;
  psq, first: Int64;
begin
  nr := AMax - AMin;
  SetLength(num, nr + 1);
  MakePrimeList;

  for psq in PrSqList do begin
    first := ((AMin + psq - 1) div psq) * psq;
    while first < AMax do begin //Eratosphenes-like sieve uses prime squares
      num[first - AMin] := 1;
      first := first + psq;
    end;
  end;

  Result := 0;
  for i := 0 to nr - 1 do
    if num[i] = 0 then
      Result := Result + 1;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  Memo1.Lines.Add(IntToStr(CountSquareless(1000000000000 - 1000000, 1000000000000)));

Delphi代码在0.1秒内给出结果607923

using namespace std;

typedef long long ll;
const int primeMax = 1000000;
int num[primeMax + 1];
ll prime[100000];
int primecnt = 0;

void Eratos()
{
    for (int i = 2; i <= primeMax; i++) num[i] = i;

    for (int i = 2; i <= primeMax; i++) {
        for (int j = 2; j <= primeMax / i ; j++) {
             num[i * j] = -1;
        }
    }

    for (int i = 2; i <= primeMax; i++)
        if (num[i] != -1) {
          prime[primecnt++] = (ll)num[i] * num[i];
      }
    cout << "last prime squared " << prime[primecnt-1] << " number " << primecnt;
 }

c ++的筛选代码

{{1}}

答案 1 :(得分:0)

鉴于问题陈述要求您找到 all 未分割的数字&#34; (原文如此),事实上你只有一个 printf并且它不在某种循环中,似乎表明你的解决方案更多的是在&#34;错&#34;分类帐的一侧而不是&#34;时间限制&#34;侧。

我建议在你担心加速之前修复 。您无法获得更少优化而不是&#34;错误&#34; : - )

第一个你应该做的事情是看看你从测试用例中给出的输入得到了什么 - 你会立刻看到速度不是问题所在:

pax> echo 1 10 | ./testprog
7

现在我的眼睛可能会变得有点旧,但即使也可以看到71,2,3,5,6,7,10之间存在差异。