I was solving a problem on leetcode and this was my code.
/*
max int 2147483647 (10^10)
max uint 4294967295 (10^10)
ULONG_MAX 18446744073709551615 (10^20)
LONG_MAX 9223372036854775807 (10^20)
USHRT_MAX 65535, SHRT_MAX 32767
*/
#include <stdio.h>
#include <math.h>
int main(void) {
int t;
scanf("%d", &t);
while (t--) {
int length;
scanf("%d", &length);
char string[length];
scanf("%s", string);
long int answer = 0;
int ones = 0;
for (int i = 0; i < length; i ) {
ones = ones (string[i] == '1') * (i 1);
if (ones & 1) {
answer = (answer (long int)pow(2, length - (i 1))) % 998244353;
}
}
printf("%ld\n", answer);
}
return 0;
}
It is working fine for smaller values (possibly values that int can hold). but when calculating large values it was giving unexpected result
then I thought that might be due to the overflow so I changed variable int answer
to long int answer
which I thought will resolve the problem, but it didn't and also broke the code for even smaller values
then I noticed I am using pow
function which will for sure exceed the limit for high values of length, As pow
gives double value in return, I was casting it to an int
with (int)pow(2, length - (i 1))
before, which I changed to (long int)pow(2, length - (i 1))
I was passing these values to test the code.
4
16
1111010010111101
2
10
6
101101
4
1111
and expected result was
49359
3
48
12
but i got
49359
65535
49152
49152
I am getting the expected result when I am using int answer
and (int)pow(...)
but if I cast answer or pow to long, I am getting unexpected result. I am not sure if this is due to cast or something else but as far as I noticed it happens only when I am casting these variables into long.
CodePudding user response:
There are multiple problems in the code:
while (t--)
will cause unexpected behavior if the value oft
entered is negative. Usewhile (t-- > 0)
char string[length];
does not have enough space forlength
characters and the null terminator. Usechar string[length 1];
scanf("%s", string);
does not provide any protection against buffer overflow. There is no simple way to tellscanf()
to read up to a variable number of bytes for%s
. Since the length can be as large as100000
, you should probably allocate the array from the heap and read the bits withgetchar()
.the code in the loop does not seem to implement a solution for the problem:
Given a binary string
S
, she defines the beauty of the string as the bitwise XOR of decimal representations of all substrings ofS
.The instructions are misleading because the result has nothing to do with the decimal representation of anything. But your code does not convert all substrings and only the result should be displayed modulo
998244353
. Applying xor to the modules would produce a different result.furthermore there is no need for
pow
to convert a binary representation: you can multiplyres
by 2 and add the value of the next digit in the loop.
To compute the resulting bitstring, consider the bit at offset i
, starting at the beginning of the string with offset 0
:
it will be XORed with itself
i
times for substrings with just a prefix removed.Then each bit with an index
j
smaller thani
will be XORedj
times for each substring with the lasti-j
bits removed.XORing
i
times will produce0
ifi
is odd, hence has the same effect as masking with the opposite of the last bit ofi
.You could use 2 nested loops for this:
for (int i = 0; i < length; i ) { int bit = (string[i] - '0') & ~i; for (j = 0; j < i; j ) { bit ^= (string[j] - '0') & ~j; } answer = (answer * 2 bit) % 998244353; }
Here is a modified version:
#include <stdio.h>
#include <stdlib.h>
int main() {
int t, i, j, c;
int string_size = 0;
unsigned char *string = NULL; /* array for the bits */
/* read the number of test cases */
if (scanf("%d", &t) != 1)
return 1;
while (t-- > 0) {
int length;
/* read the length */
if (scanf("%d", &length) != 1)
return 1;
/* discard the rest of the input line */
while ((c = getchar()) != EOF && c != '\n')
continue;
/* reallocate the string if required */
if (length > string_size) {
string_size = length;
string = realloc(string, string_size);
if (string == NULL)
return 1;
}
/* read the bits */
i = 0;
while (i < length && ((c = getchar()) == '0' || c == '1')) {
string[i ] = (unsigned char)(c - '0');
}
/* discard the rest of the input line */
while (c != EOF && c != '\n') {
c = getchar();
}
/* compute the answer one bit at a time */
long int answer = 0;
for (i = 0; i < length; i ) {
/* compute the next bit of the result string */
int bit = string[i] & ~i;
for (j = 0; j < i; j ) {
bit ^= string[j] & ~j;
}
/* compute the answer one bit at a time, reducing modulo 998244353 */
answer = (answer * 2 bit) % 998244353;
}
printf("%ld\n", answer);
}
free(string);
return 0;
}