In my code I am trying to multiply two numbers. The algorithm is simple as (k)*(k-1)^n. I stored the product (k-1)^n in variable p1 and then I multiply it with k. For n=10, k=10 (k-1)^n-1 should be 387420489 and I got this in variable p1 but on multiplying it with k, I get a negative number. I used modulus but instead of 3874208490, I get some other large positive number. What is the correct approach?
#include <iostream>
using namespace std;
typedef long long ll;
ll big = 1000000000 + 7;
ll multiply(ll a, ll b)
{
ll ans = 1;
for (int i = 1; i <= b; i++)
ans = ans * a;
return ans % big;
}
int main()
{
int t;
scanf("%d", &t);
while (t--)
{
ll n, k;
cin >> n >> k;
ll p1 = multiply(k - 1, n - 1);
cout << p1 << endl; // this gives correct value
ll p2 = (k % big) * (p1 % big);
cout << ((p2 + big) % big) % big << endl;
}
}
What is ll type? If it is just int (and I pretty sure it is), it gets overflowed, because 32-bit signed type can't store values more than (2^31)-1, which approximately equals to 2 * 10^9. You can use long long int to make it work, then your code will work with the results less than 2^63.
It's not surprising you get an overflow. I plugged your equation into wolfram alpha, fixing n at 10 and iterating over k from 0 to 100.
The curve gets very vertical, very quickly at around k = 80.
10^21 requires 70 binary bits to represent it, and you only have 63 in a long long.
You're going to have to decide what the limits of this algorithm's parameters are and pick data types corresponding. Perhaps a double would be more suitable?
link to plot is here
Related
I am doing this coding question where they ask you to enter numbers N and M, and you are supposed to output the Nth fibonacci number mod M. My code runs rather slowly and I would like to learn how to speed it up.
#include<bits/stdc++.h>
using namespace std;
long long fib(long long N)
{
if (N <= 1)
return N;
return fib(N-1) + fib(N-2);
}
int main ()
{
long long N;
cin >> N;
long long M;
cin >> M;
long long b;
b = fib(N) % M;
cout << b;
getchar();
return 0;
}
While the program you wrote is pretty much the go-to example of recursion in education, it is really a pretty damn bad algorithm as you have found out. Try to write up the call tree for fib(7) and you will find that the number of calls you make balloons dramatically.
There are many ways of speeding it up and keeping it from recalculating the same values over and over. Somebody already linked to a bunch of algorithms in the comments - a simple loop can easily make it linear in N instead of exponential.
One problem with this though is that fibonacci numbers grow pretty fast: You can hold fib(93) in a 64 bit integer, but fib(94) overflows it.
However, you don't want the N'th fibonacci number - you want the N'th mod M. This changes the challenge a bit, because as long as M is smaller than MAX_INT_64 / 2 then you can calculate fib(N) mod M for any N.
Turn your attention to Modular arithmetic and the congruence relations. Specifically the one for addition, which says (changed to C++ syntax and simplified a bit):
If a1 % m == b1 and a2 % m == b2 then (a1 + a2) % m == (b1 + b2) % m
Or, to give an example: 17 % 3 == 2, 22 % 3 == 1 => (17 + 22) % 3 == (2 + 1) % 3 == 3 % 3 == 0
This means that you can put the modulo operator into the middle of your algorithm so that you never add big numbers together and never overflow. This way you can easily calculate f.ex. fib(10000) mod 237.
There is one simple optimatimization in calling fib without calculating duplicate values. Also using loops instead of recursion may speed up the process:
int fib(int N) {
int f0 = 0;
int f1 = 1;
for (int i = 0; i < N; i++) {
int tmp = f0 + f1;
f0 = f1;
f1 = tmp;
}
return f1;
}
You can apply the modulo operator sugested by #Frodyne on top of this.
1st observation is that you can turn the recursion into a simple loop:
#include <cstdint>
std::uint64_t fib(std::uint16_t n) {
if (!n)
return 0;
std::uint64_t result[]{ 0,1 };
bool select = 1;
for (auto i = 1; i < n; ++i , select=!select)
{
result[!select] += result[select];
};
return result[select];
};
next you can memoize it:
#include <cstdint>
#include <vector>
std::uint64_t fib(std::uint16_t n) {
static std::vector<std::uint64_t> result{0,1};
if (result.size()>n)
return result[n];
std::uint64_t back[]{ result.crbegin()[1],result.back() };
bool select = 1;
result.reserve(n + 1);
for (auto i=result.size(); i < result.capacity();++i, select = !select)
result.push_back(back[!select] += back[select]);
return result[n];
};
Another option would be an algebraic formula.
cheers,
FM.
Question: https://www.codechef.com/INOIPRAC/problems/INOI1502
Here's what I'd thought off -
Have a function, f(n) which finds the factors of n
If a factor, i, is found, call f(i)
for each value of n, the function also calculates the number of non periodic strings would be equal to 2^n - (the value returned by each of the function calls)
return the number of non periodic strings and store this number in an array to prevent
Then I just call the function, f(n) modulo n to get the output
It works for smaller values, but not for larger ones
For example, when n=35 & m=99999989
My code as of now:
#include <iostream>
#include <cmath>
using namespace std;
int arr[150100];
int ans[150100];
int check(int n){
if(arr[n]>0){
return arr[n];
}
else if(n == 1){
arr[n] = 2;
return 2;
}
if(n==2){
arr[n] = 2;
return 2;
}
for(int i =1 ;i<(n/2) +1;i++){
if(n%i == 0){
ans[n] -= check(i);//2+
}
}
arr[n] = ans[n];
return ans[n];
}
int main() {
int n,m;
cin>>n>>m;
for(int i=0;i<=150100;i++){
arr[i] = 0;
ans[i] = pow (2,i);
}
std::cout<<( check(n) )%m<<endl;
}
Full problem statement:
A string is any nonempty sequence of 0s and 1s. Examples of strings are 00, 101, 111000, 1, 0, 01. The length of a string is the number of symbols in it. For example, the length of 111000 is 6. If u and v are strings, then uv is the string obtained by concatenating u and v. For example if u = 110 and v = 0010 then uv = 1100010.
A string w is periodic if there exists a string v such that w = vn = vv · · · v (n times), for some n ≥ 2. Note that in this case the length of v is strictly less than that of w. For example, 110110 is periodic, because it is vv for v = 110.
Given a positive integer N , find the number of strings of length N which are not periodic. Report the answer modulo M. The non-periodic strings of length 2 are 10 and 01. The non- periodic strings of length 3 are 001, 010, 011, 100, 101, and 110.
Input format
A single line, with two space-separated integers, N and M.
Ok, I'll start from built in type you have choose, it's not the best choice for your example: n=35 & m=99999989. Generally size of int is 32 bits, so it capable to hold maximum 2^32. So for your example you should choose a type that capable to hold minimum 35 bits.
Long long is also not good choice since you use modulo function which applies on integers, if you want to apply modulo on type bigger than int, you will prefer to use function fmod, please see http://www.cplusplus.com/reference/cmath/fmod/.
In your implementation I would prefer to use double type, on most systems it's size is 64 bits, below is code with some corrections:
#include <iostream>
#include <cmath>
using namespace std;
double arr[150100];
double ans[150100];
double check(int n){
if(arr[n]>0){
return arr[n];
}
else if(n == 1){
arr[n] = 2;
return 2;
}
if(n==2){
arr[n] = 2;
return 2;
}
for(int i =1 ;i<(n/2) +1;i++){
if(n%i == 0){
ans[n] -= check(i);//2+
}
}
arr[n] = ans[n];
return ans[n];
}
int main() {
int n,m;
cin>>n>>m;
for(int i=0;i < 150100;i++){
arr[i] = 0;
ans[i] = pow(2.0,i);
}
std::cout<<static_cast<int>(fmod(check(n),m))<<endl;
}
Please note that this fix will work only for N up to 64, because on most systems double size is 64 bits.
The second issue that you should take into account is your "ans" array, you try to initialize it with values that are much more bigger than int or double capable to hold, values that are bigger than 2^64. in this case there will be truncated data in "ans".
For this task I would prefer another approach which includes modular exponentiation rules: ab mod m = (a mod m)(b mod m) mod m = (a(b mod m)) mod m
According to description in question 2 ≤ M ≤ 10^8, so it's enough to hold array of integers in this task.
For example, to calculate 2^150000 mod 10^8, instead of evaluating 2^150000 directly, do it step by step and take modulo at each step.
I am trying to solve a question in which i need to find out the number of possible ways to make a team of two members.(note: a team can have at most two person)
After making this code, It works properly but in some test cases it shows floating point error ad i can't find out what it is exactly.
Input: 1st line : Number of test cases
2nd line: number of total person
Thank you
#include<iostream>
using namespace std;
long C(long n, long r)
{
long f[n + 1];
f[0] = 1;
for (long i = 1; i <= n; i++)
{
f[i] = i * f[i - 1];
}
return f[n] / f[r] / f[n - r];
}
int main()
{
long n, r, m,t;
cin>>t;
while(t--)
{
cin>>n;
r=1;
cout<<C(n, min(r, n - r))+1<<endl;
}
return 0;
}
You aren't getting a floating point exception. You are getting a divide by zero exception. Because your code is attempting to divide by the number 0 (which can't be done on a computer).
When you invoke C(100, 1) the main loop that initializes the f array inside C increases exponentially. Eventually, two values are multiplied such that i * f[i-1] is zero due to overflow. That leads to all the subsequent f[i] values being initialized to zero. And then the division that follows the loop is a division by zero.
Although purists on these forums will say this is undefined, here's what's really happening on most 2's complement architectures. Or at least on my computer....
At i==21:
f[20] is already equal to 2432902008176640000
21 * 2432902008176640000 overflows for 64-bit signed, and will typically become -4249290049419214848 So at this point, your program is bugged and is now in undefined behavior.
At i==66
f[65] is equal to 0x8000000000000000. So 66 * f[65] gets calculated as zero for reasons that make sense to me, but should be understood as undefined behavior.
With f[66] assigned to 0, all subsequent assignments of f[i] become zero as well. After the main loop inside C is over, the f[n-r] is zero. Hence, divide by zero error.
Update
I went back and reverse engineered your problem. It seems like your C function is just trying to compute this expression:
N!
-------------
R! * (N-R)!
Which is the "number of unique sorted combinations"
In which case instead of computing the large factorial of N!, we can reduce that expression to this:
n
[ ∏ i ]
n-r
--------------------
R!
This won't eliminate overflow, but will allow your C function to be able to take on larger values of N and R to compute the number of combinations without error.
But we can also take advantage of simple reduction before trying to do a big long factorial expression
For example, let's say we were trying to compute C(15,5). Mathematically that is:
15!
--------
10! 5!
Or as we expressed above:
1*2*3*4*5*6*7*8*9*10*11*12*13*14*15
-----------------------------------
1*2*3*4*5*6*7*8*9*10 * 1*2*3*4*5
The first 10 factors of the numerator and denominator cancel each other out:
11*12*13*14*15
-----------------------------------
1*2*3*4*5
But intuitively, you can see that "12" in the numerator is already evenly divisible by denominators 2 and 3. And that 15 in the numerator is evenly divisible by 5 in the denominator. So simple reduction can be applied:
11*2*13*14*3
-----------------------------------
1 * 4
There's even more room for greatest common divisor reduction, but this is a great start.
Let's start with a helper function that computes the product of all the values in a list.
long long multiply_vector(std::vector<int>& values)
{
long long result = 1;
for (long i : values)
{
result = result * i;
if (result < 0)
{
std::cout << "ERROR - multiply_range hit overflow" << std::endl;
return 0;
}
}
return result;
}
Not let's implement C as using the above function after doing the reduction operation
long long C(int n, int r)
{
if ((r >= n) || (n < 0) || (r < 0))
{
std::cout << "invalid parameters passed to C" << std::endl;
return 0;
}
// compute
// n!
// -------------
// r! * (n-r)!
//
// assume (r < n)
// Which maps to
// n
// [∏ i]
// n - r
// --------------------
// R!
int end = n;
int start = n - r + 1;
std::vector<int> numerators;
std::vector<int> denominators;
long long numerator = 1;
long long denominator = 1;
for (int i = start; i <= end; i++)
{
numerators.push_back(i);
}
for (int i = 2; i <= r; i++)
{
denominators.push_back(i);
}
size_t n_length = numerators.size();
size_t d_length = denominators.size();
for (size_t n = 0; n < n_length; n++)
{
int nval = numerators[n];
for (size_t d = 0; d < d_length; d++)
{
int dval = denominators[d];
if ((nval % dval) == 0)
{
denominators[d] = 1;
numerators[n] = nval / dval;
}
}
}
numerator = multiply_vector(numerators);
denominator = multiply_vector(denominators);
if ((numerator == 0) || (denominator == 0))
{
std::cout << "Giving up. Can't resolve overflow" << std::endl;
return 0;
}
long long result = numerator / denominator;
return result;
}
You are not using floating-point. And you seem to be using variable sized arrays, which is a C feature and possibly a C++ extension but not standard.
Anyway, you will get overflow and therefore undefined behaviour even for rather small values of n.
In practice the overflow will lead to array elements becoming zero for not much larger values of n.
Your code will then divide by zero and crash.
They also might have a test case like (1000000000, 999999999) which is trivial to solve, but not for your code which I bet will crash.
You don't specify what you mean by "floating point error" - I reckon you are referring to the fact that you are doing an integer division rather than a floating point one so that you will always get integers rather than floats.
int a, b;
a = 7;
b = 2;
std::cout << a / b << std::endl;
this will result in 3, not 3.5! If you want floating point result you should use floats instead like this:
float a, b;
a = 7;
b = 2;
std::cout << a / b << std::end;
So the solution to your problem would simply be to use float instead of long long int.
Note also that you are using variable sized arrays which won't work in C++ - why not use std::vector instead??
Array syntax as:
type name[size]
Note: size must a constant not a variable
Example #1:
int name[10];
Example #2:
const int asize = 10;
int name[asize];
Find the smallest number which is divisible by all numbers from 1 to N, without leaving any remainder. As number can be very large we take the answer modulo 1000000007.
I think the smallest number that would be divisible by all the number from 1 to N,would be LCM(1..N).
Example: for N = 5, that smallest number would be 60.
As 60 is the smallest number divisible by all the number form (1-5).
But for some strange reason its giving me wrong answer for large N(1000), etc.
What can cause the possible error here, is my login correct here?
Here's what i tried to Implement.
#include <iostream>
#include <vector>
using namespace std;
vector<long long> lcmArr;
const long long mod = 1000000007;
long long gcd(long long a, long long b){
if(b == 0)
{
return a;
}
return gcd(b, a%b);
}
long long lcmFumction(long long a, long long b)
{
return (a*b)/gcd(a,b);
}
int main() {
lcmArr.clear();lcmArr.resize(1002);
lcmArr[0] =0; lcmArr[1] = 1;
for(int i =2; i <=1000; i++){
lcmArr[i] = lcmFumction(lcmArr[i-1], i)%mod;
//cout<<lcmArr[i-1]<<" ";
}
int T;
cin >> T;
while(T--) {
int N;
cin>>N;
cout<<lcmArr[N]<<"\n";
}
return 0;
}
The problem is when you calculate LCM, you use division,
And
((A/B)/C) mod M != (((A/B) mod M)/C)mod M
For example (10/5/2) % 2 != ((10/5)%2)/2)%2
You should use modular inverse to calculate that.
Some explanation about modular inverse.
If we have:
(a*b) % m = 1, then b is modular inverse of a, as b % m = (1/a) % m.
Thus, if we need to calculate (x/a) % m, we can make it become (x * b ) %m.
And we know that (A*B*C)% m = ((A * B) % m)*C)% m, so, in your case, modular inverse will come in handy.
I know the answer above has already been accepted, but I think that won't be enough to solve your problem. The problem lies in the fact that the first modular LCM will take away all divisors you need to check in subsequent GCD calls, so the answer will still be wrong.
One possible solution is to keep an array of factors for the answer. Each factor will be each number from 1..N, divided by GCD(number, [all previous numbers]). For this to work, you have to code a special GCD that computes the result between a single number and an array of factors. This C++ code shows how this would work:
#include <iostream>
#include <vector>
#define lli long long int
using namespace std;
vector<lli> T;
lli gcd(lli a, lli b) {
if(b == 0)
return a;
return gcd(b, a%b);
}
lli gcd_vector(vector<lli>& a, lli b) {
lli ma = 1;
for(int i=0; i<T.size(); i++)
ma = ma*T[i]%b;
return gcd(b, ma);
}
int main() {
lli answer = 1;
for(int i=1; i<=1000; i++) {
lli factor = i/gcd_vector(T, i);
T.push_back(factor);
answer = (answer*factor)%1000000007;
}
cout << answer << endl;
}
I have written an attempt at my own RSA algorithm, but the encryption portion isn't quite working when I use fairly large numbers (nothing like the size which should be used for RSA) and I'm not sure why.
It works in the following way:
The input is a list of characters, for this example "abc"
This is converted to an array: [10,11,12]. (I have chosen 10 - 35 for lower case letters so that they are all 2 digit numbers just to make it easier)
The numbers are combined to form 121110 (using 12*100^2 + 11*100^1 + 10*100^0)
Apply the algorithm: m^e (mod n)
This is simplified using a^b (mod n) = a^c (mod n) * a^d (mod n)
This works for small values in that it can be deciphered using the decryption program which I have written.
When using larger values the output is always 1844674407188030241, with a little bit of research I found that this is roughly 2^64 (to 10 significant figures, it has been pointed out that odd numbers can't be powers of two, oops). I am sure that there is something that I have overlooked and I apologise for what (I really hope) will be a trivial question with an easy answer. Why is the output value always 2^64 and what can I change to fix it? Thank you very much for any help, here is my code:
#include <iostream>
#include <string>
#include <math.h>
int returnVal (char x)
{
return (int) x;
}
unsigned long long modExp(unsigned long long b, unsigned long long e, unsigned long long m)
{
unsigned long long remainder;
int x = 1;
while (e != 0)
{
remainder = e % 2;
e= e/2;
if (remainder == 1)
x = (x * b) % m;
b= (b * b) % m;
}
return x;
}
unsigned mysteryFunction(const std::string& input)
{
unsigned result = 0;
unsigned factor = 1;
for (size_t i = 0; i < input.size(); ++i)
{
result += factor * (input[i] - 87);
factor *= 100;
}
return result;
}
int main()
{
unsigned long long p = 70021;
unsigned long long q = 80001;
int e = 7;
unsigned long long n = p * q;
std::string foo = "ab";
for (int i = 0; i < foo.length(); i++);
{
std::cout << modExp (mysteryFunction(foo), e, n);
}
}
Your code has several problems.
Problem 1: Inconsistent use of unsigned long long.
int x = 1;
Changing this declaration in modExp to unsigned long long causes the program to give a more reasonable-looking result. I don't whether it's the correct result, but it's less than n, at least. I'm still not sure what the exact mechanism of the error was. I can see ways it would have screwed things up, but none that could have caused an output of 1844674407188030241.
Problem 2: Composite "primes".
For RSA, p and q both need to be prime. Neither p nor q is prime in your code.
70021 = 7^2 * 1429
80001 = 3^2 * 2963
In mysteryFunction, you subtract 89, which corresponds to 'W', from the input characters. You probably want to subtract '97' instead, which corresponds to 'a'.