花一點後時間排除了有關適當存儲類型,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