Last active
January 10, 2019 22:25
-
-
Save kkabdol/e676054178addef08fe19ea8e0fc5b04 to your computer and use it in GitHub Desktop.
The number of distinct integers in the created sequence
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// a[0] = S (modulo 2^31) | |
// for i = 1 to N-1 | |
// a[i] = a[i-1]*P+Q (modulo 2^31) | |
// | |
// https://www.hackerrank.com/challenges/bitset-1/forum/comments/138875 | |
#include <algorithm> | |
#include <iostream> | |
constexpr unsigned exponent = 31; | |
constexpr unsigned two_to_exponent = 1u << exponent; | |
unsigned solve_p_even( unsigned n, unsigned s, unsigned p, unsigned q ) { | |
if( p == 0 ) { | |
if( s == q ) | |
return 1; | |
return 2; | |
} | |
if( s == 0 && q == 0 ) | |
return 1; | |
unsigned a1_minus_a0 = ( p - 1 ) * s + q; | |
unsigned numerator = | |
exponent - __builtin_popcount( ( a1_minus_a0 & -a1_minus_a0 ) - 1 ); | |
unsigned denominator = __builtin_popcount( ( p & -p ) - 1 ); | |
unsigned m = numerator / denominator + ( numerator % denominator == 0 ? 1 : 2 ); | |
return std::min( m, n ); | |
} | |
unsigned solve_p_odd( unsigned n, unsigned s, unsigned p, unsigned q ) { | |
if( p == 1 ) | |
return q == 0 ? 1 : std::min( n, two_to_exponent / ( q & -q ) ); | |
if( s == 0 && q == 0 ) | |
return 1; | |
unsigned m = 1; | |
unsigned long long p_minus_1 = p - 1; | |
unsigned long long a1_minus_a0 = p_minus_1 * s + q; | |
unsigned long long p_to_m = p; | |
unsigned long long mask = ( two_to_exponent * ( p_minus_1 & -p_minus_1 ) / | |
( a1_minus_a0 & -a1_minus_a0 ) ) - | |
1; | |
while( m < n && ( p_to_m & mask ) != 1 ) { | |
p_to_m = p_to_m * p_to_m; | |
m = m * 2; | |
} | |
return std::min( m, n ); | |
} | |
unsigned solve( unsigned n, unsigned s, unsigned p, unsigned q ) { | |
if( p % 2 == 0 ) | |
return solve_p_even( n, s, p, q ); | |
return solve_p_odd( n, s, p, q ); | |
} | |
int main() { | |
unsigned n, s, p, q; | |
std::cin >> n >> s >> p >> q; | |
std::cout << solve( n, s, p, q ); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment