Huge fibonacci modulo m C++ - c++

I'm trying to calculate Fn mod m, where Fn is the nth Fibonacci number. n may be really huge, so its really not efficient to calculate Fn in a straightforward way (matrix exponentiation would work, though). The problem statement asks us to do this without calculating Fn, using the distributive property of the modulo:
(a+b)mod m = [a mod m + b mod m] mod m
(Before anyone asks me, I looked up answers to this same problem. I'd like an answer to my specific question, however, since I'm not asking about the algorithm to solve this problem)
Using this and the fact that the nth Fibonacci number is just the sum of the previous two, I don't need to store Fibonacci numbers, but rather only the results of calculating successive modulo operations. In that sense, I should have an array F of size n which has in it stored the results of iteratively calculating Fn mod m using the above property. I have managed to solve this problem using the following code. However, upon reviewing it, I stumbled upon something that rather confused me.
long long get_fibonacci_huge_mod(long long n, long long m) {
long long Fib[3] = {0, 1, 1};
long long result;
long long index;
long long period;
long long F[n+1];
F[0] = 0;
F[1] = 1;
F[2] = 1;
for (long long i = 3; i <= n; i++) {
F[i] = (F[i-2] + F[i-1]) % m;
if (F[i] == 0 && F[i+1] == 1 && F[i+2] == 1) {
period = i;
break;
}
}
index = n % period;
result = F[index];
return result;
}
This solution outputs correct results for any n and m, even if they are quite large. It might get a little bit slow when n is huge, but I'm not worried about that right now. I'm interested in specifically solving the problem this way. I'll try solving it using matrix exponentiation or any other much faster algorithm later.
So my question is as follows. At the beginning of the code, I create an array F of size n+1. Then I iterate through this array calculating Fn mod m using the distributive property. One thing that confused me after writing this loop was the fact that, since F was initialized to all zeros, how is it correctly using F[i+2], F[i+1], if they haven't been calculated yet? I assume that they are being correctly used since the algorithm outputs correct results every time. Perhaps this assumption is wrong?
My question isn't about the algorithm per se, I'm asking about what's going on inside the loop.
Thank you

This is a faulty implementation of a correct algorithm. Let us look at the corrected version first.
long long get_fibonacci_huge_mod(long long n, long long m) {
long long result;
long long index;
long long period = n+1;
long long sz = min (n+1,m*m+1); // Bound for period
long long *F = new long long[sz];
F[0] = 0;
F[1] = 1;
F[2] = 1;
for (long long i = 3; i < sz; i++) {
F[i] = (F[i-2] + F[i-1]) % m;
if (F[i] == 1 && F[i-1] == 0) { // we have got back to where we started
period = i-1;
break;
}
}
index = n % period;
result = F[index];
delete[]F;
return result;
}
So why does the original code work? Because you got lucky. The checks for i+1 and i+2 never evaluated to true because of the lucky garbage the array was initialized to. As a result this reduced to the naive evaluation of F(n) without incorporating periodicity at all.

Related

How does memoization help here?

I just solved the subset sum problem:
Given an integer array nums of size N. You are also given an integer B, you need to find whether there exists a subset in nums whose sum is B. If there exist a subset then return 1 else return 0.
Constraints are: 1 <= N <= 100; 1 <= nums[i] <= 100; 1 <= B <= 10^5;
The way I solved this problem is as below (0/1 knapsack):
vector<int> n;
int t;
unordered_map<string, long long> m;
int helper(int i, int sum) {
if(i>=n.size()) return sum==t;
string str=to_string(i)+"-"+to_string(sum);
if(m.count(str)) return m[str];
int val=helper(i+1, sum+n[i]);
val=max(val, helper(i+1, sum));
return m[str]=val;
}
int Solution::solve(vector<int> &nums, int B) {
n=nums;
t=B;
m.clear();
return helper(0,0);
}
This gets "Accepted". However, note that all the values in nums are positive; so IMO sum will only remain the same/go on increasing. i goes on increasing, too. So, we will never encounter a value previously stored in the memoization table.
But, if I remove memoization, it results in Wrong Answer for some large test case. What am I missing? Will any recursive call ever encounter a previous state?
You call helper twice, the second time with the lower sum than the first. Therefore a later call to helper could indeed have the same sum as an earlier call.
#user3386109 already gave a concrete set of num that demonstrates this. As for how often, consider the case where nums = [1, 1, ..., 1] 100 times. Then without memoization you'll call helper(100, 50) 100 choose 50 = 100,891,344,545,564,193,334,812,497,256 times. Over 100 octillion calls..takes a while.

Ways to go from a number to 0 the fastest way

So, I have a homework like this:
Given two number n and k that can reach the long long limit, we do such operation:
assign n = n / k if n is divisible by k
reduce n by 1 if n is not divisible by k
Find the smallest number of operations to go from n to 0.
This is my solution
#define ll long long
ll smallestSteps(ll n, ll k) {
int steps = 0;
if (n < k) return n;
else if (n == k) return 2;
else {
while (n != 0) {
if (n % k == 0) {
n /= k;
steps++;
}
else {
n--;
steps++;
}
}
return (ll)steps;
}
}
This solution is O(n/k) I think?
But I think that n and k could be extremely big, and thus the program could exceed the time limit of 1s. Is there any better way to do this?
Edit 1: I use ll for it to be shorter
The algorithm can be improved given these observations:
If n<k then k|(n-m) will never hold for any positive m. So the answer is n steps.
If (k|n) does not hold then the biggest number m, m<n for which it does is n - (n%k). So it takes n%k steps until (k|m) holds again.
Actually all that you need is to keep doing division with remainder using std::div (or rely on compiler to optimize) and increase steps by remainder+1.
steps=0
while(n>0)
mod = n%k
n = n/k
steps+=mod + 1
return steps
This can be done with an even simpler main program.
Convert n to base k. Let d be the number of digits in this number.
To get to 0, you will divide by k (d-1) times.
The number of times you subtract 1 is the digital sum of this number.
For instance, consider n=314, k=3.
314 in base 3 is 102122. This has 6 digits; the digital sum is 8.
You will have 6-1+8 steps ... 13 steps to 0.
Use your C++ packages to convert to the new base, convert the digits to integers, and do the array sum. This pushes all the shift-count work into module methods.
Granted this won't work for weird values of k, but you can also steal available conversion packages instead of writing your own.

Calculation error while using ceil function in C++

I m new to C++. I m trying to implement a segmented sieve to find prime numbers, between given numbers m and n. My logic might be also wrong. Below is the code i have written,
long long m;
long long n;
std::cin >> m;
std::cin >> n;
vector<bool> sieve(n-m+1,true);
for(int i=2;i<sqrt(n);i++) {
long long j = ceil(float(m)/float(i));
while(j*i <= n) {
sieve[j*i - m] = false;
j++;
}
}
The code works for small value of m (i.e. the starting number). However, when i m increasing the value of m to order 10^8. I get a seg fault because the value of (j*i-m) goes negative. During debugging for a value of m = 63458900, for i = 3, i'm getting j = 21152966, when it's supposed to be 21152967 after the ceil function.
The value of n-m is always less than 10^6.
Any help is highly appreciated. Thank You.
The value you get is off by one - it should be 21152967 after ceil.
You can simplify
ceil(float(m)/float(i))
to
(m + i - 1) / i
and thereby avoid potential imprecisions.
Substituting the corresponding values yields (63458900ll + 3 - 1)/3 which should be 21152967 on your machine.

Calculate floor(pow(2,n)/10) mod 10 - sum of digits of pow(2,n)

This is also a math related question, but I'd like to implement it in C++...so, I have a number in the form 2^n, and I have to calculate the sum of its digits ( in base 10;P ). My idea is to calculate it with the following formula:
sum = (2^n mod 10) + (floor(2^n/10) mod 10) + (floor(2^n/100) mod 10) + ...
for all of its digits: floor(n/floor(log2(10))).
The first term is easy to calculate with modular exponentiation, but I'm in trouble with the others.
Since n is big, and I don't want to use my big integer library, I can't calculate pow(2,n) without modulo. A code snippet for the first term:
while (n--){
temp = (temp << 1) % 10;
};
but for the second I have no idea. I also cannot floor them individually, since it would give '0' (2/10). Is it possible to achieve this?
(http://www.mathblog.dk/project-euler-16/ for the easier solution.) Of course I will look for other way if it cannot be done with this method. (for example storing digits in byte array, as in the comment in the link).
Edit: Thanks for the existing answers, but I look for some way to solve it mathematically. I've just came up with one idea, which can be implemented without bignum or digit-vectors, I'm gonna test if it works.
So, I have the equation above for the sum. But 2^n/10^k can be written as 2^n/2^(log2 10^k) which is 2^(n-k*log2 10). Then I take it's fractional part, and its integer part, and do modular exponentiation on the integer part: 2^(n-k*log2 10) = 2^(floor(n-k*log2 10)) * 2^(fract(n-k*log2 10)). After the last iteration I also multiply it with the fractional modulo 10. If it won't work or if I'm wrong somewhere in the above idea, I stick to the vector solution and accept an answer.
Edit: Ok, it seems doing modular exponentiation with non-integer modulo is not possible(?) (or I haven't found anything about it). So, I'm doing the digit/vector based solution.
The code does NOT work fully!
It does not give the good value: (1390 instead of 1366):
typedef long double ldb;
ldb mod(ldb x, ldb y){ //accepts doubles
ldb c(0);
ldb tempx(x);
while (tempx > y){
tempx -= y;
c++;
};
return (x - c*y);
};
int sumofdigs(unsigned short exp2){
int s = 0;
int nd = floor((exp2) * (log10(2.0))) + 1;
int c = 0;
while (true){
ldb temp = 1.0;
int expInt = floor(exp2 - c * log2((ldb)10.0));
ldb expFrac = exp2 - c * log2((ldb)10.0) - expInt;
while (expInt>0){
temp = mod(temp * 2.0, 10.0 / pow(2.0, expFrac)); //modulo with non integer b:
//floor(a*b) mod m = (floor(a mod (m/b)) * b) mod m, but can't code it
expInt--;
};
ldb r = pow(2.0, expFrac);
temp = (temp * r);
temp = mod(temp,10.0);
s += floor(temp);
c++;
if (c == nd) break;
};
return s;
};
You could create a vector of the digits using some of the techniques mentioned in this other question (C++ get each digit in int) and then just iterate over that vector and add everything up.
In the link you mention, you have the answer which will work as is for any number with n <= 63. So... why do you ask?
If you have to program your own everything then you need to know how to calculate a binary division and handle very large numbers. If you don't have to program everything, get a library for large integer numbers and apply the algorithm shown in the link:
BigNumber big_number;
big_number = 1;
big_number <<= n;
int result = 0;
while(big_number != 0) {
result += big_number % 10;
big_number /= 10;
}
return result;
Now, implementing BigNumber would be fun. From the algorithm we see that you need assignment, shift to left, not equal, modulo and division. A BigNumber class can be fully dynamic and allocate a buffer of integers to make said big number fit. It can also be written with a fixed size (as a template for example). But if you don't have the time, maybe this one will do:
https://mattmccutchen.net/bigint/
I implemented this in JavaScript as below for finding the sum of digits of 2^1000: (Check out working CodePen)
function calculate(){
var num = 0, totalDigits = 1,exponent =0,sum=0,i=0,temp=0, carry;
var arr = ['1'];
//Logic to implement how we multiply in daily life using carry forward method
while(exponent<1000){ //Mention the power
carry=0;
for(var j=arr.length-1;j>=0;j--){
temp = arr[j]*2 + carry;
arr[j]= temp%10;
carry = parseInt(temp/10);
if(carry && !j){
arr = [carry].concat(arr); //if the last nth digit multiplication with 2 yields a carry, increase the space!
}
}
exponent++;
}
for(var i=0;i<arr.length;i++){
sum = sum+parseInt(arr[i]);
}
document.getElementById('result').value = sum; //In my HTML code, I am using result textbox with id as 'result'
//console.log(arr);
//console.log(sum);
}

Coding Competitions: How to store large numbers and find its all combination modulus P

I have started doing competitive programming and most of the time i find that the input size of numbers is like
1 <= n <= 10^(500).
So i understand that it would be like 500 digits which can not be stored on simple int memory. I know c and c++.
I think i should use an array. But then i get confused on how would i find
if ( (nCr % P) == 0 ) //for all (0<=r<=n)//
I think that i would store it in an array and then find nCr. Which would require coding multiplication and division on digits but what about modulus.
Is there any other way?
Thanks.
I think you don't want to code the multiplication and division yourself, but use something like the GNU MP Bignum library http://gmplib.org/
Regarding large number libraries, I have used ttmath, which provides arbitrary length integers, floats, etc, and some really good operations, all with relatively little bulk.
However, if you are only trying to figure out what (n^e) mod m is, you can do this for very large values of e even without extremely large number calculation. Below is a function I added to my local ttmath lib to do just that:
/*!
mod power this = (this ^ pow) % m
binary algorithm (r-to-l)
return values:
0 - ok
1 - carry
2 - incorrect argument (0^0)
*/
uint PowMod(UInt<value_size> pow, UInt<value_size> mod)
{
if(pow.IsZero() && IsZero())
// we don't define zero^zero
return 2;
UInt<value_size> remainder;
UInt<value_size> x = 1;
uint c = 0;
while (pow != 0)
{
remainder = (pow & 1 == 1);
pow /= 2;
if (remainder != 0)
{
c += x.Mul(*this);
x = x % mod;
}
c += Mul(*this);
*this = *this % mod;
}
*this = x;
return (c==0)? 0 : 1;
}
I don't believe you ever need to store a number larger than n^2 for this algorithm. It should be easy to modify such that it removes the ttmath related aspects, if you don't want to use those headers.
You can find the details of the mathematics online by looking up modular exponentiation, if you care about it.
If we have to calcuate nCr mod p(where p is a prime), we can calculate factorial mod p and then use modular inverse to find nCr mod p. If we have to find nCr mod m(where m is not prime), we can factorize m into primes and then use Chinese Remainder Theorem(CRT) to find nCr mod m.
#include<iostream>
using namespace std;
#include<vector>
/* This function calculates (a^b)%MOD */
long long pow(int a, int b, int MOD)
{
long long x=1,y=a;
while(b > 0)
{
if(b%2 == 1)
{
x=(x*y);
if(x>MOD) x%=MOD;
}
y = (y*y);
if(y>MOD) y%=MOD;
b /= 2;
}
return x;
}
/* Modular Multiplicative Inverse
Using Euler's Theorem
a^(phi(m)) = 1 (mod m)
a^(-1) = a^(m-2) (mod m) */
long long InverseEuler(int n, int MOD)
{
return pow(n,MOD-2,MOD);
}
long long C(int n, int r, int MOD)
{
vector<long long> f(n + 1,1);
for (int i=2; i<=n;i++)
f[i]= (f[i-1]*i) % MOD;
return (f[n]*((InverseEuler(f[r], MOD) * InverseEuler(f[n-r], MOD)) % MOD)) % MOD;
}
int main()
{
int n,r,p;
while (~scanf("%d%d%d",&n,&r,&p))
{
printf("%lld\n",C(n,r,p));
}
}
Here, I've used long long int to stote the number.
In many. many cases in these coding competitions, the idea is that you don't actually calculate these big numbers, but figure out how to answer the question without calculating it. For example:
What are the last ten digits of 1,000,000! (factorial)?
It's a number with over five million digits. However, I can answer that question without a computer, not even using pen and paper. Or take the question: What is (2014^2014) modulo 153? Here's a simple way to calculate this in C:
int modulo = 1;
for (int i = 0; i < 2014; ++i) modulo = (modulo * 2014) % 153;
Again, you avoided doing a calculation with a 6,000 digit number. (You can actually do this considerably faster, but I'm not trying to enter a competition).