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.
Related
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.
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.
Hello I am trying a simple reverse integer operation in c++. Code below:
#include <iostream>
#include <algorithm>
#include <climits>
using namespace std;
class RevInteger {
public:
int reverse(int x)
{
int result = 0;
bool isNeg = x > 0 ? false : true;
x = abs(x);
while (x != 0)
{
result = result * 10 + x % 10;
x = x / 10;
}
if (isNeg)
result *= -1;
if (result > INT_MAX || result < INT_MIN)
return 0;
else
return (int)result;
}
};
When I give it an input as 1534236469; I want it to return me 0, instead it returns me some junk values. What is wrong in my program. Also, I am trying to use the climits lib for the purpose, is there a simpler way of doing the same?
The simplest approach is to use long long in place of int for the result, and check for overflow at the end:
long long result = 0;
/* the rest of your code */
return (int)result; // Now the cast is necessary; in your code you could do without it
Another approach is to convert the int to string, reverse it, and then use the standard library to try converting it back, and catch the problems along the way (demo):
int rev(int n) {
auto s = to_string(n);
reverse(s.begin(), s.end());
try {
return stoi(s);
} catch (...) {
return 0;
}
}
If you must stay within integers, an approach would be to check intermediate result before multiplying it by ten, and also checking for overflow after the addition:
while (x != 0) {
if (result > INT_MAX/10) {
return 0;
}
result = result * 10 + x % 10;
if (result < 0) {
return 0;
}
x = x / 10;
}
class Solution {
public:
int reverse(int x) {
int reversed = 0;
while (x != 0) {
if (reversed > INT_MAX / 10 || reversed < INT_MIN / 10) return 0;
reversed = reversed * 10 + (x % 10);
x /= 10;
}
return reversed;
}
};
If reversed bigger than 8 digit INT_MAX (INT_MAX / 10), then if we add 1 digit to reversed, we will have an int overflow. And similar to INT_MIN.
As suggested by #daskblinkenlight; changing the result as long long and type casting at the end solves the problem.
Working class:
class intReverse {
public:
int reverse(int x) {
long long result = 0; // only change here
bool isNeg = x > 0 ? false : true;
x = abs(x);
while (x != 0) {
result = result * 10 + x % 10;
x = x / 10;
}
if (isNeg) {
result *= -1;
}
if (result > INT_MAX || result < INT_MIN)
{
return 0;
}
else
{
return (int) result;
}
}
};
int reverse(int x) {
int pop = 0;
int ans = 0;
while(x) {
// pop
pop = x % 10;
x /= 10;
// check overflow
if(ans > INT_MAX/10 || ans == INT_MAX/10 && pop > 7) return 0;
if(ans < INT_MIN/10 || ans == INT_MIN/10 && pop < -8) return 0;
// push
ans = ans * 10 + pop;
}
return ans;
}
How to I reduce a chain of if statements in C++?
if(x == 3) {
a = 9876543;
}
if(x == 4) {
a = 987654;
}
if(x == 5) {
a = 98765;
}
if(x == 6) {
a = 9876;
}
if(x == 7) {
a = 987;
}
if(x == 8) {
a = 98;
}
if(x == 9) {
a = 9;
}
This is the example code.
You can generate this value mathematically, by using integer division:
long long orig = 9876543000;
long long a = orig / ((long) pow (10, x));
EDIT:
As #LogicStuff noted in the comments, it would be much more elegant to subtract 3 from x, instead of just multiplying orig by another 1000:
long orig = 9876543;
long a = orig / ((long) pow (10, x - 3));
With an array, you may do:
if (3 <= x && x <= 9) {
const int v[] = {9876543, 987654, 98765, 9876, 987, 98, 9};
a = v[x - 3];
}
Something like:
#include <iostream>
#include <string>
int main() {
int x = 4;
int a = 0;
std::string total;
for(int i = 9; i > 0 ; --i)
{
if(x <= i)
total += std::to_string(i);
}
a = std::stoi(total, nullptr);
std::cout << a << std::endl;
return 0;
}
http://ideone.com/2Cdve1
If the data can be derived, I'd recommend using one of the other answers.
If you realize their are some edge cases that end up making the derivation more complicated, consider a simple look-up table.
#include <iostream>
#include <unordered_map>
static const std::unordered_multimap<int,int> TABLE
{{3,9876543}
,{4,987654}
,{5,98765}
,{6,9876}
,{7,987}
,{8,98}
,{9,9}};
int XtoA(int x){
int a{0};
auto found = TABLE.find(x);
if (found != TABLE.end()){
a = found->second;
}
return a;
}
int main(){
std::cout << XtoA(6) << '\n'; //prints: 9876
}
Im trying to implement the Miller-Rabin primality test according to the description in FIPS 186-3 C.3.1. No matter what I do, I cannot get it to work. The instructions are pretty specific, and I dont think I missed anything, and yet Im getting true for non-prime values.
What did I do wrong?
template <typename R, typename S, typename T>
T POW(R base, S exponent, const T mod){
T result = 1;
while (exponent){
if (exponent & 1)
result = (result * base) % mod;
exponent >>= 1;
base = (base * base) % mod;
}
return result;
}
// used uint64_t to prevent overflow, but only testing with small numbers for now
bool MillerRabin_FIPS186(uint64_t w, unsigned int iterations = 50){
srand(time(0));
unsigned int a = 0;
uint64_t W = w - 1; // dont want to keep calculating w - 1
uint64_t m = W;
while (!(m & 1)){
m >>= 1;
a++;
}
// skipped getting wlen
// when i had this function using my custom arbitrary precision integer class,
// and could get len(w), getting it and using it in an actual RBG
// made no difference
for(unsigned int i = 0; i < iterations; i++){
uint64_t b = (rand() % (W - 3)) + 2; // 2 <= b <= w - 2
uint64_t z = POW(b, m, w);
if ((z == 1) || (z == W))
continue;
else
for(unsigned int j = 1; j < a; j++){
z = POW(z, 2, w);
if (z == W)
continue;
if (z == 1)
return 0;// Composite
}
}
return 1;// Probably Prime
}
this:
std::cout << MillerRabin_FIPS186(33) << std::endl;
std::cout << MillerRabin_FIPS186(35) << std::endl;
std::cout << MillerRabin_FIPS186(37) << std::endl;
std::cout << MillerRabin_FIPS186(39) << std::endl;
std::cout << MillerRabin_FIPS186(45) << std::endl;
std::cout << MillerRabin_FIPS186(49) << std::endl;
is giving me:
0
1
1
1
0
1
The only difference between your implementation and Wikipedia's is that you forgot the second return composite statement. You should have a return 0 at the end of the loop.
Edit: As pointed out by Daniel, there is a second difference. The continue is continuing the inner loop, rather than the outer loop like it's supposed to.
for(unsigned int i = 0; i < iterations; i++){
uint64_t b = (rand() % (W - 3)) + 2; // 2 <= b <= w - 2
uint64_t z = POW(b, m, w);
if ((z == 1) || (z == W))
continue;
else{
int continueOuter = 0;
for(unsigned int j = 1; j < a; j++){
z = POW(z, 2, w);
if (z == W)
continueOuter = 1;
break;
if (z == 1)
return 0;// Composite
}
if (continueOuter) {continue;}
}
return 0; //This is the line you're missing.
}
return 1;// Probably Prime
Also, if the input is even, it will always return probably prime since a is 0. You should add an extra check at the start for that.
In the inner loop,
for(unsigned int j = 1; j < a; j++){
z = POW(z, 2, w);
if (z == W)
continue;
if (z == 1)
return 0;// Composite
}
you should break; instead of continue; when z == W. By continueing, in the next iteration of that loop, if there is one, z will become 1 and the candidate is possibly wrongly declared composite. Here, that happens for 17, 41, 73, 89 and 97 among the primes less than 100.