- No usar 1LL o 1ll cuando sea necesario
// A program shows problem if we
// don't use 1ll or 1LL
#include <iostream>
using
namespace
std;
int
main()
{
int
x = 1000000;
int
y = 1000000;
// This causes overflow even
// if z is long long int
long
long
int
z = x*y;
cout << z;
return
0;
}
Output: -727379968
Es posible que obtenga algún otro valor negativo como salida. Entonces, ¿cuál es el problema aquí? Los enteros no se promocionan mucho antes de la multiplicación, siguen siendo enteros y su producto también. Luego, el producto se lanza demasiado, pero ahora estamos retrasados porque ya se ha producido un desbordamiento. Tener uno de x o y tan largo debería funcionar, ya que el otro sería promovido. También podemos usar 1LL (o 1ll). LL es el sufijo de long long, que es de 64 bits en la mayoría de las implementaciones de C/C++. Entonces 1LL, es un 1 de tipo long long.
// C++ program to show that use of 1ll
// fixes the problem in above code.
#include <iostream>
using
namespace
std;
int
main()
{
int
x = 1000000;
int
y = 1000000;
long
long
int
z = 1LL*x*y;
cout << z;
return
0;
}
Output: 1000000000000
Aquí hay otro lugar donde este truco puede ayudarte.
// Another problematic code that doesn't
// use 1LL or 1ll
#include <iostream>
using
namespace
std;
int
main()
{
// we should use 1LL or 1ll here
// instead of 1. The correct statement
// is "long long int z = 1LL << 40;"
long
long
int
z = 1 << 40;
cout << z;
return
0;
}
Output: 0
- No usar cin.ignore() con getline
// A program that shows problem if we
// don't use cin.ignore()
#include <iostream>
using
namespace
std;
int
main()
{
int
n;
cin >> n;
string s;
for
(
int
i = 0; i<n; ++i)
{
getline(cin, s);
cout << s.length() <<
" "
;
cout << s << endl;
}
return
0;
}
Input: 4 a b c d e f g h Output: 0 3 a b 3 c d 3 e f
Entonces, ¿cuál es el problema aquí?
Esto tiene poco que ver con la entrada que proporcionó usted mismo, sino más bien con el comportamiento predeterminado que exhibe getline(). Cuando proporcionó su entrada para el número entero n (cin >> n), no solo envió lo siguiente, sino que también se agregó una nueva línea implícita a la transmisión:"4\n"
Siempre se agrega una nueva línea a su entrada cuando selecciona Entrar o Regresar al enviar desde una terminal. También se usa en archivos para pasar a la siguiente línea. La nueva línea se deja en el búfer después de la extracción en n hasta la siguiente operación de E/S donde se descarta o se consume. Cuando el flujo de control llega a getline(), la nueva línea se descartará, pero la entrada cesará inmediatamente. La razón por la que esto sucede es porque la funcionalidad predeterminada de esta función dicta que debería hacerlo (intenta leer una línea y se detiene cuando encuentra una nueva línea).
Debido a que esta nueva línea inicial inhibe la funcionalidad esperada de su programa, se deduce que debe omitirse o ignorarse de alguna manera. Una opción es llamar a cin.ignore() después de la primera extracción. Descartará el siguiente carácter disponible para que la nueva línea ya no sea intrusiva.
cin.ignore(n, delim) ;
Esto extrae caracteres de la secuencia de entrada y los descarta, hasta que se extraen n caracteres o uno se compara igual a delim.// C++ program to show that use of cin.ignore()
// fixes the problem in above code.
#include <iostream>
using
namespace
std;
int
main()
{
int
n;
cin >> n;
string s;
cin.ignore(1,
'\n'
);
for
(
int
i = 0; i<n; ++i)
{
getline(cin, s);
cout << s.length() <<
" "
;
cout << s << endl;
}
return
0;
}
Input: 4 a b c d e f g h Output: 3 a b 3 c d 3 e f 3 g h
Pero, ¿qué sucede si no sabemos cuántas líneas de entrada habrá? Podemos usar esto entonces:
// C++ program to handle cases when we
// don't know how many lines of input
// are going to be there
#include <iostream>
using
namespace
std;
int
main()
{
string s;
while
(getline(cin, s))
{
if
(s.empty())
break
;
cout << s << endl;
}
return
0;
}
Input: a b c d e f g h Output: a b c d e f g h
- Un problema cuando se toman restos: en muchos problemas, debe imprimir su solución en un módulo primo grande (por ejemplo, 10 ^ 9 + 7).
// Below program shows problem if we
// don't use don't take remainders
// properly.
#include <iostream>
#define mod 1000000007
using
namespace
std;
int
main()
{
long
long
int
x, y, z;
cin >> x >> y >> z;
z = (z + x*y)%mod;
// not good practice
cout << z;
return
0;
}
Dado que z + x*y podría no encajar en long long, el código anterior puede causar problemas. La mejor manera es hacer esto:
// Program to demonstrate proper
// ways of taking remainders.
#include <iostream>
#define mod 1000000007
using
namespace
std;
int
main()
{
long
long
int
x, y, z;
cin >> x >> y >> z;
// good practice
z = ((z%mod) + ((x%mod)*(y%mod))%mod) % mod;
cout << z;
return
0;
}
Esto puede ahorrarle muchas respuestas incorrectas, por lo que es mejor tomar mod después de cada cálculo que pueda exceder mucho tiempo. Los casos de prueba generalmente están diseñados para asegurarse de que ha manejado los casos de desbordamiento correctamente.
¿Por qué funciona esto?
Porque (z + x*y)%mod es lo mismo que ((z%mod) + ((x%mod)*(y%mod))%mod)%mod. - cin y cout pueden causar TLE: en muchos programas, la causa de TLE generalmente se basa en su algoritmo. Por ejemplo, si n = 10 ^ 6 y su algoritmo se ejecuta en O (n ^ 2), entonces esto no pasará un límite de tiempo de 1 segundo. Pero digamos que ha encontrado un algoritmo que se ejecuta en O(n) para n = 10^6. Esto debería pasar el límite de tiempo de 1 segundo.
¿Qué pasa si esto está fallando?
Una posible razón es que está utilizando cin y cout para E/S en varios casos de prueba.
Puede usar scanf o printf para lo mismo. También puede usar alguna función de E/S rápida personalizada para lo mismo basada en algo como getchar() y putchar().scanf e printf son más rápidos que cin y cout. Vea esto para más detalles.
Funciones de E/S rápidas personalizadas:
// C++ program to demonstrate fast input and output
// use long long x = fast_input(); to read in x
inline
long
long
int
fast_input(
void
)
{
char
t;
long
long
int
x=0;
long
long
int
neg=0;
t =
getchar
();
while
((t<48 || t>57) && t!=
'-'
)
t =
getchar
();
if
(t ==
'-'
)
//handle negative input
{
neg = 1;
t =
getchar
();
}
while
(t>=48 && t<=57)
{
x = (x<<3) + (x<<1) + t - 48;
// x<<3 means 8*x and x<<1 means 2*x so we
// have x = 10*x+(t - 48)
t =
getchar
();
}
if
(neg)
x = -x;
return
x;
}
// use fast_output(x, 0); to print x and a newline
// use fast_output(x, 1); to print x and a ' ' after
// the x
inline
void
fast_output(
long
long
int
x,
int
mode)
{
char
a[20];
long
long
int
i=0, j;
a[0] =
'0'
;
if
(x < 0)
{
putchar
(
'-'
);
x = -x;
}
if
(x==0)
putchar
(
'0'
);
while
(x)
{
// convert each digit to character and
// store in char array
a[i++] = x%10 + 48;
x /= 10;
}
// print each character from the array
for
(j=i-1; j>=0; j--)
putchar
(a[j]);
if
(mode == 0)
putchar
(
'\n'
);
else
putchar
(
' '
);
}
Artículos relacionados:
Una mejor manera de abordar la programación competitiva
Trucos de C++ para la programación competitiva (para C++ 11)
Escribir código C/C++ de manera eficiente en la programación competitiva
Este artículo es una contribución de Hemang Sarkar . Si le gusta GeeksforGeeks y le gustaría contribuir, también puede escribir un artículo usando contribuya.geeksforgeeks.org o envíe su artículo por correo a contribuya@geeksforgeeks.org. Vea su artículo que aparece en la página principal de GeeksforGeeks y ayude a otros Geeks.
Escriba comentarios si encuentra algo incorrecto o si desea compartir más información sobre el tema tratado anteriormente.
Publicación traducida automáticamente
Artículo escrito por GeeksforGeeks-1 y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA