问题
最小值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。
我的方法。
所有数字除以平方数也除以平方素数。
使用eratosthenes的seive,计算小于sqrt(max)的所有平方素数
查找所有数字除以上面的suqare素数。
但我得到了#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++;
}
}
答案 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
现在我的眼睛可能会变得有点旧,但即使我也可以看到7
和1,2,3,5,6,7,10
之间存在差异。