Integer overflow in Russian Peasant Algorithm in c++ - c++

I came across a problem of Russian Peasant Exponentiation (RPE) Link is here which evaluates exponents much faster than the conventional method for finding x raised to the power of n.
Conventional Method
int power(int base, int exponent) {
int result = 1;
for(register int i = 1; i <= exponent; i++) {
result *= base;
}
return result;
}
I implemented the algorithm for complex numbers, given that the multiplication can lead to overflow i am printing the re(z) mod m and im(z) mod mas 2 space separated integers, but my implementation is not correct as it is causing some weird answers can anyone point out the problem, and how to correct it. Here is my code
#include<iostream>
#include<complex>
using namespace std;
class Solution {
int m;
long long int k;
complex<long long int> num;
complex<long long int> russianPeasantExponentiation(), multiply(complex<long long int>, complex<long long int>);
public:
void takeInput(), solve();
};
void Solution::takeInput() {
int a, b;
cin >> a >> b >> k >> m;
num = complex<long long int> (a, b);
}
void Solution::solve() {
complex<long long int> res = russianPeasantExponentiation();
cout << real(res) << " " << imag(res) << endl;
}
complex<long long int> Solution::russianPeasantExponentiation() {
complex<long long int> temp1(1, 0), temp2 = num;
while(k) {
if(k % 2) {
temp1 = multiply(temp1, temp2);
}
temp2 = multiply(temp2, temp2);
k /= 2;
}
return temp1;
}
complex<long long int> Solution::multiply(complex<long long int> a, complex<long long int> b) {
long long int ar = real(a), ai = imag(a), br = real(b), bi = imag(b);
complex<long long int> result(((ar * br) % m - (ai * bi) % m) % m, ((ar * bi)%m + (ai * br)%m)%m);
return result;
}
int main() {
int q;
cin >> q;
while(q--) {
Solution obj;
obj.takeInput();
obj.solve();
}
return 0;
}
The questions states that input consists of an integer q which defines the no. of queries. Each query consists of 4 numbers separated by space a, b, k, m. For each query i have to find z = (a + ib)^k since the values of re(z) and im(z) can be very large so i have to print re(z) mod m and im(z) mod m
The problem is occuring in the test case of
8 2 10 1000000000 where the expected out put is 880332800 927506432 and my out put is -119667200 -72493568

You need to replace
((ar * br) % m - (ai * bi) % m) % m
with
((ar * br) % m + m - (ai * bi) % m) % m
because you can get a negative value as a result of the expression above

This is such a neat algorithm I ended up writing my own!
I don't see how reducing intermediate results during the computation will make the maths work, quite the opposite.
Using complex<double> worked, though.
I planned on adding this algorithm to my toolbox, so It's a bit different than your implementation. I used the paper's algorithm, which yields 1 less multiplication. The way to deal with the modulus of negative numbers is in main()
#include <complex>
#include <iostream>
template <typename T>
T fastExp(T x, unsigned int e)
{
if (e == 0)
return T(1);
while (!(e & 1))
{
x *= x;
e >>= 1;
}
auto y = x;
e >>= 1;
while (e)
{
x *= x;
if (e & 1)
y *= x;
e >>= 1;
}
return y;
}
int main()
{
std::complex<double> x{ 8, 2 };
auto y = fastExp(x, 10);
long long k = 1000000000LL;
std::complex<double> z;
y -= { floor(y.real() / k), floor(y.imag() / k) };
std::complex<long long> r{ (long long)y.real(), (long long)y.imag() };
while (r.real() < 0)
r._Val[0] += k;
while (r.imag() < 0)
r._Val[1] += k;
std::cout << "result: " << r.real() << " + " << r.imag() << " i" << "\n";
}

Related

greatest divisor of a number and prime factors relation

Question is as follows :
Given two numbers n and k. For each number in the interval [1, n], your task is to calculate its largest divisor that is not divisible by k. Print the sum of all these divisors.
Note: k is always a prime number.
t=3*10^5,1<=n<=10^9, 2<=k<=10^9
My approach toward the question:
for every i in range 1 to n, the required divisors is i itself,only when that i is not a multiple of k.
If that i is multiple of k, then we have to find the greatest divisor of a number and match with k. If it does not match, then this divisor is my answer. otherwise, 2nd largest divisor is my answer.
for example,take n=10 and k=2, required divisors for every i in range 1 to 10 is 1, 1, 3, 1, 5, 3, 7, 1, 9, 5. sum of these divisors are 36. So ans=36.
My code,which works for a few test cases and failed for some.
#include<bits/stdc++.h>
using namespace std;
#define ll long long int
ll div2(ll n, ll k) {
if (n % k != 0 || n == 1) {
return n;
}
else {
for (int i = 2; i * i <= n; i++) {
if (n % i == 0) {
ll aa = n / i;
if (aa % k != 0) {
return aa;
}
}
}
}
return 1;
}
int main() {
ios_base::sync_with_stdio(false);
cin.tie(NULL);
int t;
cin >> t;
while (t--) {
ll n, k;
cin >> n >> k;
ll sum = 0, pp;
for (pp = 1; pp <= n; pp++) {
//cout << div2(pp, k);
sum = sum + div2(pp, k);
}
cout << sum << '\n';
}
}
Can someone help me where I am doing wrong or suggest me some faster logic to do this question as some of my test cases is showing TIME LIMIT EXCEED
after looking every possible explanation , i modify my code as follows:
#include<bits/stdc++.h>
using namespace std;
#define ll long long int
int main() {
ios_base::sync_with_stdio(false);
cin.tie(NULL);
int t;
cin >> t;
while (t--) {
ll n, i;
ll k, sum;
cin >> n >> k;
sum = (n * (n + 1)) / 2;
for (i = k; i <= n; i = i + k) {
ll dmax = i / k;
while (dmax % k == 0) {
dmax = dmax / k;
}
sum = (sum - i) + dmax;
}
cout << sum << '\n';
}
}
But still it is giving TIME LIMIT EXCEED for 3 test cases. Someone please help.
Like others already said, look at the constraints: t=3*10^5,1<=n<=10^9, 2<=k<=10^9.
If your test has a complexity O(n), which computing the sum via a loop has, you'll end up doing a t * n ~ 10^14. That's too much.
This challenge is a math one. You'll need to use two facts:
as you already saw, if i = j * k^s with j%k != 0, the largest divisor is j;
sum_{i=1}^t i = (t * (t+1)) / 2
We start with
S = sum(range(1, n)) = n * (n+1) / 2
then for all number of the form k * x we added too much, let's correct:
S = S - sum(k*x for x in range(1, n/k)) + sum(x for x in range(1, n/k))
= S - (k - 1) * (n/k) * (n/k + 1) / 2
continue for number of the form k^2 * x ... then k^p * x until the sum is empty...
Ok, people start writing code, so here's a small Python function:
def so61867604(n, k):
S = (n * (n+1)) // 2
k_pow = k
while k_pow <= n:
up = n // k_pow
S = S - (k - 1) * (up * (up + 1)) // 2
k_pow *= k
return S
and in action here https://repl.it/repls/OlivedrabKeyProjections
In itself this is more of a mathematical problem:
If cur = [1..n], as you have already noticed, the largest divisor = dmax = cur is, if cur % k != 0, otherwise dmax must be < cur. From k we know that it is at most divisible into other prime numbers... Since we want to make sure that dmax is not divisible by k we can do this with a while loop... whereby this is certainly also more elegantly possible (since dmax must be a prime number again due to the prime factorization).
So this should look like this (without guarantee just typed down - maybe I missed something in my thinking):
#include <iostream>
int main() {
unsigned long long n = 10;
unsigned long long k = 2;
for (auto cur_n = decltype(n){1}; cur_n <= n; cur_n++)
{
if (cur_n % k != 0) {
std::cout << "Largest divisor for " << cur_n << ": " << cur_n << " (SELF)" << std::endl;
} else {
unsigned long long dmax= cur_n/k;
while (dmax%k == 0)
dmax= dmax/k;
std::cout << "Largest divisor for " << cur_n << ": " << dmax<< std::endl;
}
}
}
I wonder if something like this is what One Lyner means.
(Note, this code has two errors in it, which are described in the comments, as well as can be elucidated by One Lyner's new code.)
C++ code:
#include <vector>
#include <iostream>
using namespace std;
#define ll long long int
int main()
{
ios_base::sync_with_stdio(false);
cin.tie(NULL);
int t;
cin >> t;
while (t--) {
ll n;
ll k, _k, result;
vector<ll> powers;
cin >> n >> k;
result = n * (n + 1) / 2;
_k = k;
while (_k <= n) {
powers.push_back(_k);
_k = _k * k;
}
for (ll p : powers) {
ll num_js = n / p;
result -= num_js * (num_js + 1) / 2 * (p - 1);
int i = 0;
while (p * powers[i] <= n) {
result += powers[i] * (p - 1);
i = i + 1;
}
}
cout << result << '\n';
}
}

Sum to infinity of geometric sequence

Question:
Write C++ function to evaluate the following formula for a given x:
The following code was designed in C++ on Visual Studio to be a solution of the above mentioned problem. However whenever I run the code what I am returned is the value of x; or the same value I input.
I don't understand what the problem may be, so I would appreciate any help given.
#include <iostream>
using namespace std;
unsigned long fact(int n) {
if (n <= 1) {
return 1;
}
else {
return n * fact(n - 1);
}
}
unsigned long f(int x, int n) {
static unsigned long term;
static unsigned long sum = 0;
do {
term = pow(x, (2 * n + 1)) / fact((2 * n) + 1);
n++;
sum += term;
} while (term < 0.000001);
return sum;
}
int main() {
int y = 0;
int x;
cout << "enter x" << endl;
cin >> x;
cout << f(x, y) << endl;
system("pause");
}
I suggest you don't calculate powers and factorials on each iteration. Each next term can be generated by multiplying the previous one by x^2 / [n(n+1)]:
double sinh_in_disguise(const double x) {
const double x_sq = x * x;
double term = x;
double sum = 0;
double n = 2;
while (true) {
const double new_sum = sum + term;
if (new_sum == sum)
break;
sum = new_sum;
term *= x_sq / (n * (n + 1));
n += 2;
}
return sum;
}
int main() {
std::cout.precision(16);
double x = 2.019;
std::cout << sinh_in_disguise(x) << std::endl; // prints 3.699001094869803
std::cout << std::sinh(x) << std::endl; // prints 3.699001094869803
}
put double datatype in the whole code and it will work perfectly

Calculate Huge Fibonacci number modulo M in C++

Problem statement : Given two integers n and m, output Fn mod m (that is, the remainder of Fn when divided by m).
Input Format. The input consists of two integers n and m given on the same line (separated by a space).
Constraints. 1 ≤ n ≤ 10^18, 2 ≤ m ≤ 10^5
Output Format. Output Fn mod m.
I tried the following program and it didn't work. The method pi is returning the right Pisano period though for any number as per http://webspace.ship.edu/msrenault/fibonacci/fiblist.htm
#include <iostream>
long long pi(long long m) {
long long result = 2;
for (long long fn2 = 1, fn1 = 2 % m, fn = 3 % m;
fn1 != 1 || fn != 1;
fn2 = fn1, fn1 = fn, fn = (fn1 + fn2) % m
) {
result++;
}
return result;
}
long long get_fibonaccihuge(long long n, long long m) {
long long periodlength = pi(m);
int patternRemainder = n % periodlength;
long long *sum = new long long[patternRemainder];
sum[0] = 0;
sum[1] = 1;
for (int i = 2; i <= patternRemainder; ++i)
{
sum[i] = sum[i - 1] + sum[i - 2];
}
return sum[patternRemainder] % m;
}
int main() {
long long n, m;
std::cin >> n >> m;
std::cout << get_fibonaccihuge(n, m) << '\n';
}
The exact program/logic is working well in python as expected. What's wrong withthis cpp program ? Is it the data types ?
Performing 10^18 additions isn't going to be very practical. Even on a teraflop computer, 10^6 seconds is still 277 hours.
But 10^18 ~= 2^59.8 so there'll be up to 60 halving steps.
Calculate (a,b) --> (a^2 + b^2, 2ab + b^2) to go from (n-1,n)th to (2n-1,2n)th consecutive Fibonacci number pairs in one step.
At each step perform the modulus calculation for each operation. You'll need to accommodate integers up to 3*1010 &leq; 235 in magnitude (i.e. up to 35 bits).
(cf. a related older answer of mine).
This was my solution for this problem, it works well and succeeded in the submission test ...
i used a simpler way to get the pisoano period ( pisano period is the main tricky part in this problem ) ... i wish to be helpful
#include <iostream>
using namespace std;
unsigned long long get_fibonacci_huge_naive(unsigned long long n, unsigned long long m)
{
if (n <= 1)
return n;
unsigned long long previous = 0;
unsigned long long current = 1;
for (unsigned long long i = 0; i < n - 1; ++i)
{
unsigned long long tmp_previous = previous;
previous = current;
current = tmp_previous + current;
}
return current % m;
}
long long get_pisano_period(long long m)
{
long long a = 0, b = 1, c = a + b;
for (int i = 0; i < m * m; i++)
{
c = (a + b) % m;
a = b;
b = c;
if (a == 0 && b == 1)
{
return i + 1;
}
}
}
unsigned long long get_fibonacci_huge_faster(unsigned long long n, unsigned long long m)
{
n = n % get_pisano_period(m);
unsigned long long F[n + 1] = {};
F[0] = 0;
F[-1] = 1;
for (int i = 1; i <= n; i++)
{
F[i] = F[i - 1] + F[i - 2];
F[i] = F[i] % m;
}
return F[n];
}
int main()
{
unsigned long long n, m;
std::cin >> n >> m;
std::cout << get_fibonacci_huge_faster(n, m) << '\n';
}

How to multiply a number with 3.5 without using any standard operator like *,-,/,% etc?

The Question is pretty straight forward.I am given a number and I want to multiply it with 3.5 i.e to make number n=3.5n .I am not allowed to use any operator like
+,-,*,/,% etc.But I can use Bitwise operators.
I have tried by myself but It is not giving precise result like my program gives output 17 for 5* 3.5 which is clearly wrong.How can I modify my program to show correct result.
#include<bits/stdc++.h>
using namespace std;
double Multiply(int n)
{
double ans=((n>>1)+ n + (n<<1));
return ans;
}
int main()
{
int n; // Enter the number you want to multiply with 3.5
cin>>n;
double ans=Multiply(n);
cout<<ans<<"\n";
return 0;
}
Sorry I cannot comment yet. The problem with your question is that bitwise operations are usually only done on ints. This is mainly because of the way that numbers are stored.
When you have a normal int, you have a sign bit followed by data bits, pretty simple and straight forward but once you get to floating point numbers that simple patern is different. Here is a good explanation stackoverflow.
Also, the way I would solve your problem without using +/-/*// and so on would be
#include <stdlib.h> /* atoi() */
#include <stdio.h> /* (f)printf */
#include <assert.h> /* assert() */
int add(int x, int y) {
int carry = 0;
int result = 0;
int i;
for(i = 0; i < 32; ++i) {
int a = (x >> i) & 1;
int b = (y >> i) & 1;
result |= ((a ^ b) ^ carry) << i;
carry = (a & b) | (b & carry) | (carry & a);
}
return result;
}
int negate(int x) {
return add(~x, 1);
}
int subtract(int x, int y) {
return add(x, negate(y));
}
int is_even(int n) {
return !(n & 1);
}
int divide_by_two(int n) {
return n >> 1;
}
int multiply_by_two(int n) {
return n << 1;
}
Source
From your solution, you may handle odd numbers manually:
double Multiply(unsigned int n)
{
double = n + (n << 1) + (n >> 1) + ((n & 1) ? 0.5 : 0.);
return ans;
}
but it still use +
One solution would be to use fma() from <cmath>:
#include <cmath>
double Multiply(int n)
{
return fma(x, 3.5, 0.0);
}
LIVE DEMO
Simply.
First realize that 3.5 = 112 / 32 = (128 - 16) / 32.
Than you do:
int x128 = ur_num << 7;
int x16 = ur_num << 4;
to subtract them use:
int add(int x, int y) {
int carry = 0;
int result = 0;
int i;
for(i = 0; i < 32; ++i) {
int a = (x >> i) & 1;
int b = (y >> i) & 1;
result |= ((a ^ b) ^ carry) << i;
carry = (a & b) | (b & carry) | (carry & a);
}
return result;
}
int negate(int x) {
return add(~x, 1);
}
int subtract(int x, int y) {
return add(x, negate(y));
}
and than just simply do:
int your_res = subtract(x128, x16) >> 5;

how to reduce execution time

Currently the following problem is taking 3.008** seconds to execute for some testcase provided on hackerearth.com where allowed time is 3.0 seconds so i get time limit error. Please help to reduce execution time.
Problem:
Alice has just learnt multiplying two integers. He wants to multiply two integers X and Y to form a number Z.To make the problem interesting he will choose X in the range [1,M] and Y in the range [1,N].Help him to find the number of ways in which he can do this.
Input
First line of the input is the number of test cases T. It is followed by T lines. Each line has three space separated integers, the numbers Z, M and N.
Output
For each test case output a single integer, the number of ways.
Constraints
1 <= T <= 50
1 <= Z <= 10^12
1 <= M <= 10^12
1 <= N <= 10^12
CODE:
#include <iostream>
using namespace std;
int chk_div(long long a,long long b)
{
if(((a/b) * (b) )==a)return 1;
return 0;
}
int main()
{
int t;
long i,j,count;
long n,m,z;
cin>>t;
while(t--)
{count=0;
cin>>z>>m>>n;
if(m>z)m=z;
if(n>z)n=z;
if (m>n)m=n;
for(i=1;i<=m;i++)
{
if(chk_div(z,i))count++;
}
cout<<count<<"\n";
}
return 0;
}
The main problem with performance here is the fact that your inner loop does about 10^12 iterations. You can reduce it a million times to sqrt(z) <= 10^6.
The trick here is to notice that Alice can write z = x * y if and only if he can write z = y * x. Also, either x <= sqrt(z) or y <= sqrt(z). Using these facts you can iterate only up to square root of z to count all cases.
I believe this should get the job done (idea from #zch's answer):
#include <iostream>
#include <cmath>
auto MAX = [] (int A, int B) -> bool { return A > B ? A : B; };
auto MIN = [] (int A, int B) -> bool { return A < B ? A : B; };
using std::cout;
using std::cin;
int main() {
long long Z, M, N, T, low, high, temp, div;
int ans;
for (cin >> T; T--; ) {
cin >> Z >> M >> N;
temp = MIN(M, N);
low = MIN(sqrt(Z), temp);
high = MAX(M, N);
for( ans = 0; low > 0 && (Z / low) <= high; --low ) {
if ( Z % low == 0) {
++ans;
div = Z / low;
ans += (div != low && div <= temp);
}
//cout << temp << " * " << Z / temp << " = " << Z << "\n";
}
cout << ans << "\n";
}
return 0;
}
Will be adding comments in a bit
Code with comments:
#include <iostream>
#include <cmath>
auto MAX = [] (int A, int B) -> bool { return A > B ? A : B; };
auto MIN = [] (int A, int B) -> bool { return A < B ? A : B; };
using std::cout;
using std::cin;
int main() {
long long Z, M, N, T, low, high, temp, div;
int ans;
for (cin >> T; T--; ) {
cin >> Z >> M >> N;
temp = MIN(M, N);
low = MIN(sqrt(Z), temp);//Lowest value <--We start iteration from this number
high = MAX(M, N); //Maximum value
for( ans = 0; low > 0 && (Z / low) <= high; --low ) {
//Number of things going on in this for-loop
//I will start by explaining the condition:
//We want to keep iterating until either low is below 1
// or when the expression (Z / low) > high.
//Notice that as the value of low approaches 0,
//the expression (Z / low) approaches inf
if ( Z % low == 0) {
//If this condition evaluates to true, we know 2 things:
/*Z is divisible by this value of low and
low is in the range of MIN(M,N) <--true*/
/*Because of our condition, (Z / low) is
within the range of MAX(M, N) <--true*/
++ans;
div = Z / low;
//This second part checks if the opposite is true i.e.
/*the value of low is in the range of
MAX(M, N) <--true*/
/*the value (Z / low) is in the range of
MIN(M, N) <--true only in some cases*/
ans += (div != low && div <= temp);
//(div != low) is to avoid double counting
/*An example of this is when Z, M, N have the values:
1000000, 1000000, 1000000
The value of low at the start is 1000 */
}
}
cout << ans << "\n";
}
return 0;
}
In fact, you have to resolve the problem in a different way:
find the Prime decomposition:
so Z = A^a * B^b * ... * P^p with A, B, .., P prime numbers
and so you just have to compute the number of possibilities from a, b, ... p.
(So the result is up to (1 + a) * (1 + b) * ... * (1 + p) depending of M&N constraints).
Your if(((a/b) * (b) ) == a) return 1; will always return 1. Why are you dividing A with B (a/b) then multiply the result by B. This is ambiguous because, your answer will be A. when you say, (a/b) * (b). B`s will cancel each other out and you are left with A as your answer. And so basically you are comparing if A == A, which is true.