花一点后时间排除了有关适当存储类型,gcc代码/内存模型以及升级/溢出的各种问题问题,我想我已经找到了一个我对这个问题满意的方法。
随着数据的大小,默认的代码/内存模型很好。存储在a
阵列中的值完全在unsigned
类型内,允许静态声明a[1000000]
工作而不会导致段错误。 (4M存储要求)
结果值符合unsigned long
(x86_64)或unsigned long long
(x86)。但是,如果结果计算未被转换为unsigned long
,则会存在一个微妙的问题,因为这两项中的任何一项都不会导致升级。
就这样,我想我会这种方式发布到的情况下,任何解决方案还有很好奇:
#include <stdio.h>
#define LMAX 868800
int main (int argc, char **argv) {
if (argc < 2) {
fprintf (stderr, "Error: insufficient input, usage: %s <filename>\n", argv[0]);
return 1;
}
char s[LMAX] = {0};
char *p = s;
unsigned a[LMAX] = {0};
unsigned long res = 0;
unsigned n1s = 0;
unsigned n0s = 0;
size_t len = 0;
size_t i = 1;
FILE *fp = NULL;
if (!(fp = fopen (argv[1], "r"))) {
fprintf (stderr, "error: file open failed.\n");
return 1;
}
if (!(fgets (s, LMAX - 1, fp))) {
fprintf (stderr, "error: failed to read line from file.\n");
return 1;
}
fclose (fp);
/* fill a[i] with number of 1's before i in s */
while (*p && *p != '\n')
{
a[i] = a[i-1] + *p - '0';
if (*p == '1') n1s += 1; else n0s +=1;
p++; i++;
}
len = p - s;
p = s;
i = 1;
/* for each '0' in s, multiply 1's before i with 1's after i
and add product to result (i.e. the # of 101's for that 0) */
while (*p && *p != '\n')
{
if (*p == '0')
res += (unsigned long)a[i - 1] * (a[len] - a[i]);
p++; i++;
}
printf ("\n num 1's : %u\n num 0's : %u\n length : %zu\n results : %lu\n\n",
n1s, n0s, len, res);
return 0;
}
回答
$ ./bin/num101s d434839c-d-input-d4340a6.txt
num 1's : 434105
num 0's : 434684
length : 868789
results : 13653596984029524
该解决方案的数据文件可以在这里找到截至解决方案的日期:Input Data
倾倒到汇编程序后,出现如下克提供了一个指令优势在Linux/x86_64的原始比较:
a[i] = a[i-1] + *p - '0';
原:由``的scanf使用
a[i] = a[i-1] + (*p == '1');
1.您的输入缓冲器()''可能截断的输入端。更好地从文件中读取输入字符串。 (或使用该文本输入时出现其他问题)。 2.如果你使用''stdint.h''或''cstdint''头文件和类型如''uint64_t''而不是非便携式的''unsigned long long'',那么你不会感到惊讶。 – BitTickler 2015-03-25 06:27:46
我使用cin >> s在C++中尝试了相同的代码,其中s是一个字符串,它给出了相同的结果。我不明白为什么scanf可能会截断输入? – Chadi 2015-03-25 08:06:24
你在哪里提出逻辑总结'1'和'0'来得到答案?逻辑看起来有缺陷,或者发布的答案有缺陷。在'868789'字符串中有'434105''''''',''434684''''','868789'字符串,根据你的代码给出了'868206'作为答案,同时看着你发布的答案: '18446708952791232852'这只是有点害羞溢出未签名的长长的MAX。我认为你的方程式是可疑的。 – 2015-03-25 08:19:38