Arrays core.exception.OutOfMemoryError@(0)使用大型动态数组 导入标准数学; 进口标准品; 进口std.stdio; BigInt和最小因子(长N){ BigInt f(int n){ 返回BigInt(n)*(BigInt(n)+1)/2-1; } INTV=铸造(int)(sqrt(浮动(N)); bool[]使用; 已使用。长度=v+1; BigInt-ret; BigInt整理; BigInt[]s_sum,s_cnt,l_cnt,l_sum; s_总和长度=v+1; l_总和长度=v+1; s_cnt.length=v+1; l_cnt.length=v+1; 对于(long i=0;i
而言,答案是Arrays core.exception.OutOfMemoryError@(0)使用大型动态数组 导入标准数学; 进口标准品; 进口std.stdio; BigInt和最小因子(长N){ BigInt f(int n){ 返回BigInt(n)*(BigInt(n)+1)/2-1; } INTV=铸造(int)(sqrt(浮动(N)); bool[]使用; 已使用。长度=v+1; BigInt-ret; BigInt整理; BigInt[]s_sum,s_cnt,l_cnt,l_sum; s_总和长度=v+1; l_总和长度=v+1; s_cnt.length=v+1; l_cnt.length=v+1; 对于(long i=0;i,arrays,d,biginteger,dynamic-arrays,Arrays,D,Biginteger,Dynamic Arrays,而言,答案是std.math.pow()函数中的无提示整数溢出 产量 import std.math; import std.bigint; import std.stdio; BigInt sum_min_pfactor(long N){ BigInt f(int n) { return BigInt(n)*(BigInt(n)+1) / 2 - 1; } int v = cast(int)(sqrt(float(N))); bool[]
std.math.pow()
函数中的无提示整数溢出
产量
import std.math;
import std.bigint;
import std.stdio;
BigInt sum_min_pfactor(long N){
BigInt f(int n) {
return BigInt(n)*(BigInt(n)+1) / 2 - 1;
}
int v = cast(int)(sqrt(float(N)));
bool[] used;
used.length = v+1;
BigInt ret;
BigInt finish;
BigInt[] s_sum,s_cnt,l_cnt,l_sum;
s_sum.length = v+1;
l_sum.length = v+1;
s_cnt.length = v+1;
l_cnt.length = v+1;
for (long i = 0; i <= v; i++) {
s_cnt[i] = i - 1;
s_sum[i] = f(cast(int)i);
}
for (long i = 1; i <= v; i++) {
l_cnt[i] = N / cast(int)i - 1;
l_sum[i] = f(cast(int)(N) / cast(int)i);
}
for (long p = 2; p <= v; p++) {
if (s_cnt[p] == s_cnt[p-1]) {
continue;
}
BigInt p_cnt = s_cnt[p-1];
BigInt p_sum = s_sum[p - 1];
long q = p * p;
ret = ret + p * (l_cnt[p] - p_cnt);
l_cnt[1] = l_cnt[1] - l_cnt[p] + p_cnt;
l_sum[1] = l_sum[1] - (l_sum[p] - p_sum) * p;
long interval = (p & 1) + 1;
if (v > N / q) {
finish = N / q;
}
else {
finish = v;
}
for (long i = p+interval; i <= finish; i += interval){
if (used[i]) {
continue;
}
long d = i * p;
if (d <= v) {
l_cnt[i] = l_cnt[i] - l_cnt[d] + p_cnt;
l_sum[i] = l_sum[i] - (l_sum[d] - p_sum) * p;
}
else {
long t = N / d;
l_cnt[i] = l_cnt[i] - s_cnt[t] + p_cnt;
l_sum[i] = l_sum[i] - (s_sum[t] - p_sum) * p;
}
}
if (q <= v) {
for (long i = q; i < finish; i += p*interval){
used[i] = true;
}
}
for (long i = v; i >= q - 1; i--) {
long t = i / p;
s_cnt[i] = s_cnt[i] - s_cnt[t] + p_cnt;
s_sum[i] = s_sum[i] - (s_sum[t] - p_sum) * p;
}
}
return l_sum[1] + ret;
}
void main () {
writeln(sum_min_pfactor(pow(10,12)));
}
是
现在sqrt(-727379968)
是-nan
.Cast to integer给出int.min
,约为-2 GiB。数组的length
属性是无符号的。因此每个数组的type.sizeof
*2 GiB大小解释了内存不足错误
解决方案:将后缀L添加到一个或两个数字,例如
-727379968
1000000000000
使用-g编译时,除非您已经知道,否则它应该准确地告诉您引发异常的位置。您是以32位还是64位进行编译?如果是32位,则可用内存会减少,垃圾收集器更可能意外地锁定大数组而不释放它们(对于32位上的大数组,错误指针指向它的几率有点高,然后GC会认为它可能仍在使用,因此无法释放它)尝试使用-g和-m64标志进行编译,但未发生任何更改。输出没有告诉我异常发生的位置,但我知道在声明BigInt向量时会发生异常。虽然这对10^9有效,但它为10^10及更高的值提供了不正确的值。10^10应为2220827240957,而D返回22447055208362030368(奇怪,因为它实际上比正确答案高,所以我不确定这一次是否是溢出问题)。我没有看你的计算。我的观点是
pow(int,int)
返回错误的值,从10^10开始。使用pow(long,long)
OutOfMemoryError应该消失。至少从10^14开始,您的计算也会受到整数溢出的影响:cast(int)(N)会截断N中的一些位。但是值中的错误发生得更早。我已经将pow设置为使用long,但我不知道还有什么可能导致这些错误。请将参数类型从f(int)更改为f(long)移除所有的施法(int)。如果你从pow(10,10L)开始,那么你会得到10^10的正确答案。
-727379968
1000000000000
writeln(sum_min_pfactor(pow(10L,9L)));