Choose maximum number in array so that their GCD is > 1 - c++

Question:
Given an array arr[] with N integers.
What is the maximum number of items that can be chosen from the array so that their GCD is greater than 1?
Example:
4
30 42 105 1
Answer: 3
Constransts
N <= 10^3
arr[i] <= 10^18
My take:
void solve(int i, int gcd, int chosen){
if(i > n){
maximize(res, chosen);
return;
}
solve(i+1, gcd, chosen);
if(gcd == -1) solve(i+1, arr[i], chosen+1);
else{
int newGcd = __gcd(gcd, arr[i]);
if(newGcd > 1) solve(i+1, newGcd, chosen+1);
}
}
After many tries, my code still clearly got TLE, is there any more optimized solution for this problem?

Interesting task you have. I implemented two variants of solutions.
All algorithms that are used in my code are: Greatest Common Divisor (through Euclidean Algorithm), Binary Modular Exponentiation, Pollard Rho, Trial Division, Fermat Primality Test.
First variant called SolveCommon() iteratively finds all possible unique factors of all numbers by computing pairwise Greatest Common Divisor.
When all possible unique factors are found one can compute count of each unique factor inside each number. Finally maximal count for any factor will be final answer.
Second variant called SolveFactorize() finds all factor by doing factorization of each number using three algorithms: Pollard Rho, Trial Division, Fermat Primality Test.
Pollard-Rho factorization algorithm is quite fast, it has time complexity O(N^(1/4)), so for 64-bit number it will take around 2^16 iterations. To compare, Trial Division algorithm has complexity of O(N^(1/2)) which is square times slower than Pollard Rho. So in code below Pollard Rho can handle 64 bit inputs, although not very fast.
First variant SolveCommon() is much faster than second SolveFactorize(), especially if numbers are quite large, timings are provided in console output after following code.
Code below as an example provides test of random 100 numbers each 20 bit. 64 bit 1000 numbers are too large to handle by SolveFactorize() method, but SolveCommon() method solves 1000 64-bit numbers within 1-2 seconds.
Try it online!
#include <cstdint>
#include <random>
#include <tuple>
#include <unordered_map>
#include <algorithm>
#include <set>
#include <iostream>
#include <chrono>
#include <cmath>
#include <map>
#define LN { std::cout << "LN " << __LINE__ << std::endl; }
using u64 = uint64_t;
using u128 = unsigned __int128;
static std::mt19937_64 rng{123}; //{std::random_device{}()};
auto CurTime() {
return std::chrono::high_resolution_clock::now();
}
static auto const gtb = CurTime();
double Time() {
return std::llround(std::chrono::duration_cast<
std::chrono::duration<double>>(CurTime() - gtb).count() * 1000) / 1000.0;
}
u64 PowMod(u64 a, u64 b, u64 const c) {
u64 r = 1;
while (b != 0) {
if (b & 1)
r = (u128(r) * a) % c;
a = (u128(a) * a) % c;
b >>= 1;
}
return r;
}
bool IsFermatPrp(u64 N, size_t ntrials = 24) {
// https://en.wikipedia.org/wiki/Fermat_primality_test
if (N <= 10)
return N == 2 || N == 3 || N == 5 || N == 7;
for (size_t trial = 0; trial < ntrials; ++trial)
if (PowMod(rng() % (N - 3) + 2, N - 1, N) != 1)
return false;
return true;
}
bool FactorTrialDivision(u64 N, std::vector<u64> & factors, u64 limit = u64(-1)) {
// https://en.wikipedia.org/wiki/Trial_division
if (N <= 1)
return true;
while ((N & 1) == 0) {
factors.push_back(2);
N >>= 1;
}
for (u64 d = 3; d <= limit && d * d <= N; d += 2)
while (N % d == 0) {
factors.push_back(d);
N /= d;
}
if (N > 1)
factors.push_back(N);
return N == 1;
}
u64 GCD(u64 a, u64 b) {
// https://en.wikipedia.org/wiki/Euclidean_algorithm
while (b != 0)
std::tie(a, b) = std::make_tuple(b, a % b);
return a;
}
bool FactorPollardRho(u64 N, std::vector<u64> & factors) {
// https://en.wikipedia.org/wiki/Pollard%27s_rho_algorithm
auto f = [N](auto x) -> u64 { return (u128(x + 1) * (x + 1)) % N; };
auto DiffAbs = [](auto x, auto y){ return x >= y ? x - y : y - x; };
if (N <= 1)
return true;
if (IsFermatPrp(N)) {
factors.push_back(N);
return true;
}
for (size_t trial = 0; trial < 8; ++trial) {
u64 x = rng() % (N - 2) + 1;
size_t total_steps = 0;
for (size_t cycle = 1;; ++cycle) {
bool good = true;
u64 y = x;
for (u64 i = 0; i < (u64(1) << cycle); ++i) {
x = f(x);
++total_steps;
u64 const d = GCD(DiffAbs(x, y), N);
if (d > 1) {
if (d == N) {
good = false;
break;
}
//std::cout << N << ": " << d << ", " << total_steps << std::endl;
if (!FactorPollardRho(d, factors))
return false;
if (!FactorPollardRho(N / d, factors))
return false;
return true;
}
}
if (!good)
break;
}
}
factors.push_back(N);
return false;
}
void Factor(u64 N, std::vector<u64> & factors) {
if (N <= 1)
return;
if (1) {
FactorTrialDivision(N, factors, 1 << 8);
N = factors.back();
factors.pop_back();
}
FactorPollardRho(N, factors);
}
size_t SolveFactorize(std::vector<u64> const & nums) {
std::unordered_map<u64, size_t> cnts;
std::vector<u64> factors;
std::set<u64> unique_factors;
for (auto num: nums) {
factors.clear();
Factor(num, factors);
//std::cout << num << ": "; for (auto f: factors) std::cout << f << " "; std::cout << std::endl;
unique_factors.clear();
unique_factors.insert(factors.begin(), factors.end());
for (auto f: unique_factors)
++cnts[f];
}
size_t max_cnt = 0;
for (auto [_, cnt]: cnts)
max_cnt = std::max(max_cnt, cnt);
return max_cnt;
}
size_t SolveCommon(std::vector<u64> const & nums) {
size_t const K = nums.size();
std::set<u64> cmn(nums.begin(), nums.end()), cmn2, tcmn;
std::map<u64, bool> used;
cmn.erase(1);
while (true) {
cmn2.clear();
used.clear();
for (auto i = cmn.rbegin(); i != cmn.rend(); ++i) {
auto j = i;
++j;
for (; j != cmn.rend(); ++j) {
auto gcd = GCD(*i, *j);
if (gcd != 1) {
used[*i] = true;
used[*j] = true;
cmn2.insert(gcd);
cmn2.insert(*i / gcd);
cmn2.insert(*j / gcd);
break;
}
}
if (!used[*i])
tcmn.insert(*i);
}
cmn2.erase(1);
if (cmn2.empty())
break;
cmn = cmn2;
}
//for (auto c: cmn) std::cout << c << " "; std::cout << std::endl;
std::unordered_map<u64, size_t> cnts;
for (auto num: nums)
for (auto c: tcmn)
if (num % c == 0)
++cnts[c];
size_t max_cnt = 0;
for (auto [_, cnt]: cnts)
max_cnt = std::max(max_cnt, cnt);
return max_cnt;
}
void TestRandom() {
size_t const cnt_nums = 1000;
std::vector<u64> nums;
for (size_t i = 0; i < cnt_nums; ++i) {
nums.push_back((rng() & ((u64(1) << 20) - 1)) | 1);
//std::cout << nums.back() << " ";
}
//std::cout << std::endl;
{
auto tb = Time();
std::cout << "common " << SolveCommon(nums) << " time " << (Time() - tb) << std::endl;
}
{
auto tb = Time();
std::cout << "factorize " << SolveFactorize(nums) << " time " << (Time() - tb) << std::endl;
}
}
int main() {
TestRandom();
}
Output:
common 325 time 0.061
factorize 325 time 0.005

I think you need to search among all possible prime numbers to find out which prime number can divide most element in the array.
Code:
std::vector<int> primeLessEqualThanN(int N) {
std::vector<int> primes;
for (int x = 2; x <= N; ++x) {
bool isPrime = true;
for (auto& p : primes) {
if (x % p == 0) {
isPrime = false;
break;
}
}
if (isPrime) primes.push_back(x);
}
return primes;
}
int maxNumberGCDGreaterThan1(int N, std::vector<int>& A) {
int A_MAX = *std::max_element(A.begin(), A.end()); // largest number in A
std::vector<int> primes = primeLessEqualThanN(std::sqrt(A_MAX));
int max_count = 0;
for (auto& p : primes) {
int count = 0;
for (auto& n : A)
if (n % p == 0)
count++;
max_count = count > max_count ? count : max_count;
}
return max_count;
}
Note that in this way you cannot find out the value of the GCD, the code is based on that we dont need to know it.

Related

The next prime number

Among the given input of two numbers, check if the second number is exactly the next prime number of the first number. If so return "YES" else "NO".
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
int nextPrime(int x){
int y =x;
for(int i=2; i <=sqrt(y); i++){
if(y%i == 0){
y = y+2;
nextPrime(y);
return (y);
}
}
return y;
}
int main()
{
int n,m, x(0);
cin >> n >> m;
x = n+2;
if(n = 2 && m == 3){
cout << "YES\n";
exit(0);
}
nextPrime(x) == m ? cout << "YES\n" : cout << "NO\n";
return 0;
}
Where is my code running wrong? It only returns true if next number is either +2 or +4.
Maybe it has something to do with return statement.
I can tell you two things you are doing wrong:
Enter 2 4 and you will check 4, 6, 8, 10, 12, 14, 16, 18, ... for primality forever.
The other thing is
y = y+2;
nextPrime(y);
return (y);
should just be
return nextPrime(y + 2);
Beyond that your loop is highly inefficient:
for(int i=2; i <=sqrt(y); i++){
Handle even numbers as special case and then use
for(int i=3; i * i <= y; i += 2){
Using a different primality test would also be faster. For example Miller-Rabin primality test:
#include <iostream>
#include <cstdint>
#include <array>
#include <ranges>
#include <cassert>
#include <bitset>
#include <bit>
// square and multiply algorithm for a^d mod n
uint32_t pow_n(uint32_t a, uint32_t d, uint32_t n) {
if (d == 0) __builtin_unreachable();
unsigned shift = std::countl_zero(d) + 1;
uint32_t t = a;
int32_t m = d << shift;
for (unsigned i = 32 - shift; i > 0; --i) {
t = ((uint64_t)t * t) % n;
if (m < 0) t = ((uint64_t)t * a) % n;
m <<= 1;
}
return t;
}
bool test(uint32_t n, unsigned s, uint32_t d, uint32_t a) {
uint32_t x = pow_n(a, d, n);
//std::cout << " x = " << x << std::endl;
if (x == 1 || x == n - 1) return true;
for (unsigned i = 1; i < s; ++i) {
x = ((uint64_t)x * x) % n;
if (x == n - 1) return true;
}
return false;
}
bool is_prime(uint32_t n) {
static const std::array witnesses{2u, 3u, 5u, 7u, 11u};
static const std::array bounds{
2'047u, 1'373'653u, 25'326'001u, 3'215'031'751u, UINT_MAX
};
static_assert(witnesses.size() == bounds.size());
if (n == 2) return true; // 2 is prime
if (n % 2 == 0) return false; // other even numbers are not
if (n <= witnesses.back()) { // I know the first few primes
return (std::ranges::find(witnesses, n) != std::end(witnesses));
}
// write n = 2^s * d + 1 with d odd
unsigned s = 0;
uint32_t d = n - 1;
while (d % 2 == 0) {
++s;
d /= 2;
}
// test widtnesses until the bounds say it's a sure thing
auto it = bounds.cbegin();
for (auto a : witnesses) {
//std::cout << a << " ";
if (!test(n, s, d, a)) return false;
if (n < *it++) return true;
}
return true;
}
And yes, that is an awful lot of code but it runs very few times.
Something to do with the return statement
I would say so
y = y+2;
nextPrime(y);
return (y);
can be replaced with
return nextPrime(y + 2);
Your version calls nextPrime but fails to do anything with the return value, instead it just returns y.
It would be more usual to code the nextPrime function with another loop, instead of writing a recursive function.

Prime-checking every element of a 10^6 array

My goal is to figure out whether each element of an array is a prime or not.
Example:
Input: int A[5]={1,2,3,4,5}
Output: bool P[5]={0,1,1,0,1}
The problem is the array size is up to 10^6. I tried the most efficient prime-checking algorithm
(code: http://cpp.sh/9ewxa) but just the "cin" and "prime_checking" take really long time. How should I solve this problem, Thanks.
Your "most efficient" prime test is actually horribly inefficient. Something like the Miller-Rabin primality test is much faster on a one by one basis. If your input are below 4.3 billion (i.e. uint32_t) then you only need to do 3 tests: a = 2, 7, and 61. For numbers in the uint64_t range it's 12 tests.
If you have a large array of integers then computing all primes up to some maximum might be faster than repeated tests. See Sieve of Eratosthenes for a good way to compute all primes fast. But it's impractical if your input numbers can be larger than 4 billion due to the memory required.
Here is some code that computes a Sieve up to UINT32_MAX+1 and then checks Miller-Rabin has the same results as the sieve: https://gist.github.com/mrvn/137fb0c8a5c78dbf92108b696ff82d92
#include <iostream>
#include <cstdint>
#include <array>
#include <ranges>
#include <cassert>
#include <bitset>
uint32_t pow_n(uint32_t a, uint32_t d, uint32_t n) {
if (d == 0) return 1;
if (d == 1) return a;
uint32_t t = pow_n(a, d / 2, n);
t = ((uint64_t)t * t) % n;
if (d % 2 == 0) {
return t;
} else {
return ((uint64_t)t * a) % n;
}
};
bool test(uint32_t n, unsigned s, uint32_t d, uint32_t a) {
//std::cout << "test(n = " << n << ", s = " << s << ", d = " << d << ", a = " << a << ")\n";
uint32_t x = pow_n(a ,d ,n);
//std::cout << " x = " << x << std::endl;
if (x == 1 || x == n - 1) return true;
for (unsigned i = 1; i < s; ++i) {
x = ((uint64_t)x * x) % n;
if (x == n - 1) return true;
}
return false;
}
bool is_prime(uint32_t n) {
static const std::array witnesses{2u, 3u, 5u, 7u, 11u, 13u, 17u, 19u, 23u, 29u, 31u, 37u};
static const std::array bounds{
2'047llu, 1'373'653llu, 25'326'001llu, 3'215'031'751llu,
2'152'302'898'747llu, 3'474'749'660'383llu,
341'550'071'728'321llu, 341'550'071'728'321llu /* no bounds for 19 */,
3'825'123'056'546'413'051llu,
3'825'123'056'546'413'051llu /* no bound for 29 */,
3'825'123'056'546'413'051llu /* no bound for 31 */,
(unsigned long long)UINT64_MAX /* off by a bit but it's the last bounds */,
};
static_assert(witnesses.size() == bounds.size());
if (n == 2) return true; // 2 is prime
if (n % 2 == 0) return false; // other even numbers are not
if (n <= witnesses.back()) { // I know the first few primes
return (std::ranges::find(witnesses, n) != std::end(witnesses));
}
// write n = 2^s * d + 1 with d odd
unsigned s = 0;
uint32_t d = n - 1;
while (d % 2 == 0) {
++s;
d /= 2;
}
// test widtnesses until the bounds say it's a sure thing
auto it = bounds.cbegin();
for (auto a : witnesses) {
//std::cout << a << " ";
if (!test(n, s, d, a)) return false;
if (n < *it++) return true;
}
return true;
}
template<std::size_t N>
auto composite() {
std::bitset<N / 2 + 1> is_composite;
for (uint32_t i = 3; (uint64_t)i * i < N; i += 2) {
if (is_composite[i / 2]) continue;
for (uint64_t j = i * i; j < N; j += 2 * i) is_composite[j / 2] = true;
}
return is_composite;
}
bool slow_prime(uint32_t n) {
static const auto is_composite = composite<UINT32_MAX + 1llu>();
if (n < 2) return false;
if (n == 2) return true;
if (n % 2 == 0) return false;
return !is_composite.test(n / 2);
}
int main() {
/*
std::cout << "2047: ";
bool fast = is_prime(2047);
bool slow = slow_prime(2047);
std::cout << (fast ? "fast prime" : "");
std::cout << (slow ? "slow prime" : "");
std::cout << std::endl;
*/
//std::cout << "2: prime\n";
for (uint64_t i = 0; i <= UINT32_MAX; ++i) {
if (i % 1000000 == 1) { std::cout << "\r" << i << " "; std::cout.flush(); }
bool fast = is_prime(i);
bool slow = slow_prime(i);
if (fast != slow) std::cout << i << std::endl;
assert(fast == slow);
//std::cout << i << ": " << (is_prime(i) ? "prime" : "") << std::endl;
}
}
The sieve takes ~15s to compute and uses 256MB of memory, verifying Miller-Rabin takes ~12m45s or 765 times slower than the sieve. Which tells me that if you are testing more than 85 million 32bit numbers for primes then just compute them all with a sieve. Since the sieve is O(n^2) it only gets better if your maximum input is smaller.

Check if number is a tribonacci number

Tribonacci numbers are defined as below. I am trying to write a program that checks if a number is a tribonacci number. I have wrote the function, but how can I acctually check if the number is a trib number with this? Because when I enter 45, it wont return anything.
T0=0
T1=1
T2=2
Tn=Tn-1 + Tn-2 + Tn-3 (for n>2)
int trib(int n)
{
if (n == 0 || n == 1 || n == 2)
{
cout << "YES";
}
if (n >= 2)
{
return trib(n - 1) + trib(n - 2) + trib(n - 3);
}
}
int main()
{
int input;
cin >> input;
cout << trib(input);
}
If input
3
45
then output
YES
NO
Other than memoization + recursion, an old style approach is to use a while loop and stop if the value >=n:
#include <iostream>
bool trib(int n)
{
if (n == 0 || n == 1 || n == 2) {return true;}
int a = 0, b = 1, c = 2, d = a+b+c;
while(d < n)
{
a = b; b = c; c = d; d = a+b+c;
}
if (d == n) {return true;} return false;
}
int main()
{
int input; std::cin >> input;
if (trib(input)) {std::cout << "YES";} else {std::cout << "NO";}
}
Result :
3 --> YES
11 --> YES
45 --> NO
Your implementation of recursion (without memoization) will have exponentially time complexity.
Edit: To the second question: I have to input number betwen 0<= && <= 1000000 So I need to make for loop to count 1000000 tribonacci numbers? This will take year.
Seriously? A good to average computers will loop from 1 -> 10^6 in less than 1 second.
Not mentioning that from 1 -> 10^6 based on your formula there's only... 23 Tribonacci number:
#include <iostream>
bool trib(int n)
{
if (n == 0 || n == 1 || n == 2) {return true;}
int a = 0, b = 1, c = 2, d = a+b+c;
while(d < n)
{
a = b; b = c; c = d; d = a+b+c;
}
if (d == n) {return true;} return false;
}
int main()
{
int counter = 0;
for (int i = 1; i <= 1000000; i++)
{
if (trib(i)) {std::cout << i << '\n'; counter++;}
}
std::cout << "Counter : " << counter;
}
Result:
1
2
3
6
11
20
37
68
125
230
423
778
1431
2632
4841
8904
16377
30122
55403
101902
187427
344732
634061
Counter : 23
There are several problems.
You need to understand that the values are growing strongly exponential. Already the 24th value will be greater then 1000000.
Then, your function does not work as specified. You also made a very slow implementation. But does not matter in this case.
But then, you made a wrong design. What you need to use is memoization. Sounds complicated, but is not. Simply precalculate the first 25 trib numbers, and the check, if the input is such a number.
Basically very simple. There are one million possible solutions. Here is a straightforward one based on your original approach:
constexpr size_t MaxNumbers = 25u;
int trib(int n)
{
if (n < 3) return n;
return trib(n - 1) + trib(n - 2) + trib(n - 3);
}
int main()
{
int tribNumber[MaxNumbers]{};
for (int i{}; i < MaxNumbers; ++i) {
tribNumber[i] = trib(i);
}
std::cout << "\nEnter number in the range 0...1'000'000: ";
unsigned int numberToCheck{};
if (std::cin >> numberToCheck and numberToCheck <= 1'000'000) {
bool found{};
for (int i{}; i < MaxNumbers; ++i) {
if (tribNumber[i] == numberToCheck) {
found = true;
}
}
if (found)
std::cout << "Yes\n";
else
std::cout << "No\n";
}
else {
std::cerr << "\nError: Wrong Input\n";
}
return 0;
}
By the way. All trib numbers can be easily calculated at runtime. This will make your program ultrafast and very compact. I cannot imagine a better solution.
#include <iostream>
#include <array>
#include <algorithm>
// Begin of all done during compile time -------------------------------------------------------------------
constexpr unsigned int getTribonacciNumber(size_t index) noexcept {
if (index < 3) return index;
unsigned int f0{ 0u }, f1{ 1ull }, f2{ 2ull }, f3{};
index -= 2;
while (index--) { f3 = f2 + f1 + f0; f0 = f1; f1 = f2; f2 = f3; }
return f2;
}
// Some helper to create a constexpr std::array initilized by a generator function
template <typename Generator, size_t ... Indices>
constexpr auto generateArrayHelper(Generator generator, std::index_sequence<Indices...>) {
return std::array<decltype(std::declval<Generator>()(size_t{})), sizeof...(Indices) > { generator(Indices)... };
}
template <size_t Size, typename Generator>
constexpr auto generateArray(Generator generator) {
return generateArrayHelper(generator, std::make_index_sequence<Size>());
}
constexpr size_t MaxIndexForTribonacci = 25u;
// This is the definition of a std::array<unsigned int, 93> with all Tribonacci numbers in it
constexpr auto trib = generateArray<MaxIndexForTribonacci>(getTribonacciNumber);
// End of: All done during compile time -----------------------------------------------------------
// The only code executed during runtime
int main() {
// Show all Tribonacci numbers up to border value
for (const unsigned int t : trib) std::cout << t << '\n';
return 0;
}
See, everything is done during compile time. The resulting array is a compile time array. No calculation at all is done during runtime.
And if you want to addapt this program for your specific requiremens, then youcan use the below:
#include <iostream>
#include <array>
#include <algorithm>
// Begin of all done during compile time -------------------------------------------------------------------
constexpr unsigned int getTribonacciNumber(size_t index) noexcept {
if (index < 3) return index;
unsigned int f0{ 0u }, f1{ 1ull }, f2{ 2ull }, f3{};
index -= 2;
while (index--) { f3 = f2 + f1 + f0; f0 = f1; f1 = f2; f2 = f3; }
return f2;
}
// Some helper to create a constexpr std::array initilized by a generator function
template <typename Generator, size_t ... Indices>
constexpr auto generateArrayHelper(Generator generator, std::index_sequence<Indices...>) {
return std::array<decltype(std::declval<Generator>()(size_t{})), sizeof...(Indices) > { generator(Indices)... };
}
template <size_t Size, typename Generator>
constexpr auto generateArray(Generator generator) {
return generateArrayHelper(generator, std::make_index_sequence<Size>());
}
constexpr size_t MaxIndexForTribonacci = 25u;
// This is the definition of a std::array<unsigned int, 93> with all Tribonacci numbers in it
constexpr auto trib = generateArray<MaxIndexForTribonacci>(getTribonacciNumber);
// End of: All done during compile time -----------------------------------------------------------
// The only code executed during runtime
int main() {
std::cout << "\nEnter number in the range 0...1'000'000: ";
unsigned int numberToCheck{};
if (std::cin >> numberToCheck and numberToCheck <= 1'000'000) {
if (binary_search(trib.begin(), trib.end(), numberToCheck))
std::cout << "Yes\n";
else
std::cout << "No\n";
}
else {
std::cerr << "\nError: Wrong Input\n";
}
return 0;
}
This approach will outperform nearly everything . . .
I think, without using recursion, the program might become a lot faster and easier. we will just see if input matches any of trib0,trib1,trib2.
tribonacci= 0, 0, 1, 1, 2, 4, 7, 13, 24, 44, 81, 149, 274, 504
trib(n)= 0 1 2 0 1 2 0 1 2 0 1 2 0 1
#include <iostream>
using namespace std ;
int main(int argc, char const *argv[])
{
int n;
cin>> n;
int trib0 = 0, trib1 = 0, trib2 = 1;
if (n == trib0 || n == trib1 || n == trib2)
{
cout<<"YES, it is tribonacci\n";
return 0;
}
while(trib0<=n)
{
trib0 = trib0 + trib1 + trib2;
if (n == trib0)
{
cout<<"YES, it is tribonacci\n";
return 0;
}
trib1 = trib0 + trib1 + trib2;
if ( n == trib1)
{
cout<<"YES, it is tribonacci\n";
return 0;
}
trib2 = trib0 + trib1 + trib2;
if (n == trib2)
{
cout<<"YES, it is tribonacci\n";
return 0;
}
}
cout<<"No, it's not\n";
return 0;
}

A problem relevate to bitmask (or operation) and segment

I'm trying to solve this problem:
Given three integers N, L, and R, find the integer M between L and R (inclusive) that maximizes M|N (the bitwise-OR of M and N). If there are multiple such values of M, return the least of them.
For example: N=100,L=50,R=60. The result is 59. Because 100|59 reaches the maximum value and 50<=59<=60.
This is my attempt:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
int main(){
ll n,m,l,r,i,tmp,res,first,second,vt,dau,third=0,aka,check_high=0;
while(cin>>n>>l>>r){
tmp=0;dau=0;
for(i=31;i>=0;i--){
first = (l>>i)&1;
second = (r>>i)&1;
third = (n>>i)&1;
if(first==0&&second==0&&dau==0) continue;
dau=1;
if(first==1&&dau==1&&tmp==0) {tmp|=(1<<i);continue;}
if(first==0&&dau==1&&tmp==0) if(third==0) {tmp|=(1<<i);continue;}
if(first==0&&second==0&&third==0){
if(tmp|(1<<i)<=r) tmp|=(1<<i);
continue;
}
if(first==0&&second==1&&third==0){
if(tmp|(1<<i)<=r) tmp|=(1<<i);
continue;
}
if(first==1&&second==0&&third==0){
if(tmp|(1<<i)<=r) tmp|=(1<<i);
continue;
}
if(first==1&&second==1&&third==0){
if(tmp|(1<<i)<=r) tmp|=(1<<i);
continue;
}
}
cout<<tmp<<'\n';
}
return 0;
}
My idea is to browse each bit from left to right (it's mean form 31'st bit down to 0's bit) of L,R,N. Then, use the comparative statement to find the number M that satisfies the problem , specifically like above.
But when submit solution, I got Wrong Answer, this means, my algorithm is false, ans I'm stucking in ideal so solve this problem, can you help me this stuck ?
Without params validation
uint32_t getM(uint32_t L, uint32_t R, uint32_t N) {
auto M = L;
for (int bit = sizeof(L) * 8; bit > 0;) {
const decltype(L) value = 1 << (--bit);
if (value & N) {
if (value & M) {
decltype(L) check_value = M & (~value);
for (int i = bit; i > 0;) {
check_value |= (1 << (--i));
}
if (check_value >= L) {
M = check_value;
}
}
}
else {
if (!(value & M)) {
decltype(L) check_value = M | value;
for (int i = bit; i > 0;) {
check_value &= (~(1 << (--i)));
}
if (check_value <= R) {
M = check_value;
}
}
}
}
return M;
}
int main(int, char**)
{
std::cout << "M=" << getM(50, 60, 100) << std::endl;
std::cout << "M=" << getM(184, 270, 103) << std::endl;
return 0;
}
Output:
M=59
M=264

Getting wrong answer for Project Euler #27

I'm working on Project Euler #27 in C++:
Euler published the remarkable quadratic formula:
n² + n + 41
It turns out that the formula will produce 40 primes for the
consecutive values n = 0 to 39. However, when n = 40, 40² + 40 + 41 =
40(40 + 1) + 41 is divisible by 41, and certainly when n = 41, 41² +
41 + 41 is clearly divisible by 41.
Using computers, the incredible formula n² − 79n + 1601 was
discovered, which produces 80 primes for the consecutive values n = 0
to 79. The product of the coefficients, −79 and 1601, is −126479.
Considering quadratics of the form:
n² + an + b, where |a| < 1000 and |b| < 1000
where |n| is the modulus/absolute value of n
e.g. |11| = 11 and |−4| = 4
Find the product of the coefficients, a and b, for the quadratic
expression that produces the maximum number of primes for consecutive
values of n, starting with n = 0.
I keep getting -60939 when the real answer is -59231. What am I missing?
#include <iostream>
#include "Helper.h"
using namespace std;
int formula(int a, int b, int n) {
return ((n * n) + (a * n) + b);
}
int main() {
int most = 0;
int ansA = 0;
int ansB = 0;
bool end = false;
for(int a = 999; a >= -999; a--) {
for(int b = 999; b >= 2; b--) { //b must be prime
if(Helper::isPrime(b)) {
end = false;
for(int n = 0; !end; n++) {
if(!Helper::isPrime(formula(a, b, n))) {
if(n-1 > most) {
most = n-1;
ansA = a;
ansB = b;
}
end = true;
}
}
}
}
}
cout << ansA << " * " << ansB << " = " << ansA * ansB << " with " << most << " primes." << endl;
return 0;
}
In case it's the problem, here is my isPrime function:
bool Helper::isPrime(int num) {
if(num == 2)
return true;
if(num % 2 == 0 || num == 1 || num == 0)
return false;
int root = (int) sqrt((double)num) + 1;
for(int i = root; i >= 2; i--) {
if (num % i == 0)
return false;
}
return true;
}
You are allowing a to be negative, and your formula returns an int. Does calling Helper::isPrime with a negative number even make sense (in other words, does Helper::isPrime take an unsigned int?)
Here is my java version. Hope it helps:
static int function(int n, int a, int b){
return n*n + a*n + b;
}
static int consequitive_Primes(int a, int b, HashSet<Integer> primes){
int n = 0;
int number = 0;
while(true){
if(!primes.contains(function(n, a, b)))
break;
number++;
n++;
}
return number;
}
static HashSet<Integer> primes (int n){
ArrayList<Integer> primes = new ArrayList<Integer>();
primes.add(3);
for(int i=3; i<n;i+=2){
boolean isPrime = true;
for(Integer k:primes){
if(i%k==0){
isPrime = false;
break;
}
}
if(isPrime) primes.add(i);
}
return new HashSet<Integer>(primes);
}
static long q27(){
HashSet<Integer> primes = primes(1000);
int max = 0;
int max_ab = 0;
for(int a = -999; a<1000;a++){
for(int b = -999; b<1000;b++){
int prime_No = consequitive_Primes(a,b,primes);
if(max<prime_No){
max = prime_No;
max_ab = a*b;
}
}
}
return max_ab;
}