这是一个问题:我们需要在一个由0和1组成的字符串中计算101的数量。 101是字符串的任何子序列。
Ex:10101有4 101。
我很确定我正确地解决了它。对于每个零,我在它之前和之后预先计算1的数量然后乘以答案然后将结果添加到res。
对于由长度为1000000的字符串组成的测试用例,代码给出了错误的答案。
我想知道我的代码中的问题在哪里?
输出应该 18446708952791232852 ,但我的代码是 22531786
这是我的代码:
char s[1000005];
unsigned long long ans, res, a[1000005];
int main()
{
int n;
scanf("%s", s);
n = strlen(s);
a[0] = 0; res = 0;
for(int i = 1;i <= n;++i)
a[i] = a[i - 1] + (s[i - 1] == '1');
for(int i = 1;i <= n;++i)
if(s[i - 1] == '0') {
ans = a[n] - a[i];
ans *= a[i - 1];
res += ans;
//if(ans < 0 || res < 0) printf("%lld %lld\n", ans, res);
}
printf("%llu\n", res);
return 0;
}
答案 0 :(得分:0)
在花了一些时间来解决围绕适当的存储类型,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';
原:
a[i] = a[i-1] + (*p == '1');