how to check divisibility of a very long number in c++? - c++

How to check divisibility of a very long number in c++?
i have to check if (3*n*n+3*n-1) is divisible by 2 , 3 and 5 and n can be upto 10^10 so long long int is also doubtful to work although i have tried doing this:
unsigned long long int gg4,l;
gg4=(3*n*n+3*n-1);
if(gg4%3==0){
gg4=gg4/3;
}
if(gg4%2==0){
gg4=gg4/2;
}
if(gg4%5==0){
gg4=gg4/2;
}
But i guess this wont work because of the range of n so please help! :)
after this i also need to divide (3*n*n+3*n-1) by that factor so please help!

To expand on my comment, there are two cases when (3*n*n+3*n-1) % 5 == 0, namely
n = 5 * m + 1
n = 5 * m + 3
For m an integer.
So in fact you don't need to calculate a long anything, you can work directly with n, and never even calculate 3 * n * n + 3 * n - 1 in the first place.
Just check:
n % 5 == 1 || n % 5 == 3

Related

Find minimum number of digits required to make a given number

We have to find the minimum number of digits required to make a given number, for example: 14 => 95 (9 + 5 = 14) is two digits which is the minimum to form 14.
int moves(int n) {
int m = 0; // Minimum count
while (n-9 >= 0) { // To place maximum number of 9's
n -= 9;
m++;
}
if (n == 0) { // If only nines made up the number
return m;
}
else {
m++;
return m;
}
}
I am getting a TLE (runtime time limit exceeded) by an online judge. How can I improve it or is there a better approach?
Your code starts by looking at how many times 9 fits into that number. This can be done way more easily:
int m = n/9;
This suffices since we do an integer division, in which the remainder is thrown away. Note that if n would be float or another floating type, this would not work.
The question left is if it is divisible by 9 or not. If not, we have one additional digit. This can be done by the modulo operator (made it verbose for ease of understanding):
bool divisible_by_nine = (n % 9 == 0);
Assuming that you might not know the modulo operator, it returns the remainder of an integer division, 47 % 9 = 2 since 47 / 9 = 5 remainder 2.
Without it, you would go with
int remainder = n - 9*m;
bool divisible = (remainder == 0);
Combined:
int required_digits(int number)
{
bool divisible = (number % 9 == 0);
return number/9 + (divisible ? 0 : 1);
}
Or in a single line, depending on how verbose you want it to be:
int required_digits(int number)
{
return number/9 + (number % 9 == 0 ? 0 : 1);
}
Since there isn't any loop, this is in Θ(1) and thus should work in your required time limit.
(Technically, the processor might as well handle the division somewhat like you did internally, but it is very efficient at that. To be absolutely correct, I'd have to add "assuming that division is a constant time operation".)
Your solution works fine. You can try the shorter:
return (n%9==0)? n/9 : n/9 +1 ;
Shorter, but less easy to read...
Or a compromise:
if (n%9==0) // n can be divided by 9
return n/9;
else
return n/9+1;
Explanation
We know that every number a can be represented as
(a_n * 10 ^ n) + ... + (a_2 * 10 ^ 2) + (a_1 * 10) + (a_0)
where a_k are digits
and 10^n = 11...11 * 9 + 1 (n digits 1).
Meaning that number 10^n can be represented as the sum of 11...11 + 1 digits.
Now we can write a as (a_n * 11..11 * 9 + a_n) + ...
After grouping by 9 (help, I don't know English term for this. Factoring?)
(a_n * 11..11 + a_n-1 * 11..11 + ... a_1) * 9 + (a_n + a_n-1 + ... + a_1 + a_0)
Which I'll write as b_9 * 9 + b_1.
This means that number a can be represented as the sum of b_9 digits 9 + how much is needed for b_1 (this is recursive by the way)
To recapitulate:
Let's call function f
If -10 < digit < 10, the result is 1.
Two counters are needed, c1 and c2.
Iterate over digits
For every ith digit, multiply by i digit number 11..11 and add the result to c1
Add the ith digit to c2
The result is c_1 + f(c_2)
And for practice, implement this in a non-recursive way.
As you guess, you need to iterate on a lower number to a bigger one, like 111119 is fine, but we want the lowest one... Your answer is wrong. The lowest would be 59!
You can brute force and it will work, but for a bigger number you will struggle, so you need to guess first: How many minimum digits do I need to find my solution?
For instance, if you want to find 42, just add as much 9 you need to overflow the result!
9 + 9 + 9 + 9 + 9 = 45. When you find the overflow, you know that the answer is lower than 99999.
Now how much do I need to decrease the value to get the correct answer, 3 as expected?
So 99996, 99969, etc... will be valid! But you want to lower, so you have to decrease the greatest unit (the left one of course!).
The answer would be 69999 = 42!
int n = 14;
int r = 0;
for (int i = i; i < 10 /*if you play with long or long long*/; i++)
if (i * 9 >= n)
{
for (int j = 0; j < i; j++)
r = r * 10 + 9;
while (is_correct(r, n) == false)
{
// Code it yourself!!
}
return (r);
}
Now it correctly returns true or false. You can make it return the number that r is actually a decrease what you need to decrease! It's not the fastest way possible, and there is always a faster way, with a binary shift, but this algorithm would work just fine!

sum multiples in a given range

well I want to sum up the multiples of 3 and 5. Not too hard if I want just the sum upon to a given number, e.g. -> up to 60 the sum is 870.
But what if I want just the first 15 multiples?
well one way is
void summation (const unsigned long number_n, unsigned long &summe,unsigned int &counter );
void summation (const unsigned long number_n, unsigned long &summe,unsigned int &counter )
{
unsigned int howoften = 0;
summe = 0;
for( unsigned long i = 1; i <=number_n; i++ )
if (howoften <= counter-1)
{
if( !( i % 3 ) || !( i % 5 ) )
{
summe += i;
howoften++;
}
}
counter = howoften;
return;
}
But as expected the runtime is not accceptable for a counter like 1.500.000 :-/
Hm I tried a lot of things but I cannot find a solution by my own.
I also tried a faster summation algorithm like (dont care bout overflow at this point):
int sum(int N);
int sum(int N)
{
int S1, S2, S3;
S1 = ((N / 3)) * (2 * 3 + (N / 3 - 1) * 3) / 2;
S2 = ((N / 5)) * (2 * 5 + (N / 5 - 1) * 5) / 2;
S3 = ((N / 15)) *(2 * 15 + (N / 15 - 1) * 15) / 2;
return S1 + S2 - S3;
}
or even
unsigned long sum1000 (unsigned long target);
unsigned long sum1000 (unsigned long target)
{
unsigned int summe = 0;
for (unsigned long i = 0; i<=target; i+=3) summe+=i;
for (unsigned long i = 0; i<=target; i+=5) summe+=i;
for (unsigned long i = 0; i<=target; i+=15) summe-=i;
return summe;
}
But I'm not smart enough to set up an algorithm which is fast enough (I say 5-10 sec. are ok)
The whole sum of the multiples is not my problem, the first N multiples are :)
Thanks for reading, and if u have any ideas, it would be great
Some prerequisites:
(dont care bout overflow at this point)
Ok, so lets ignore that completely.
Next, the sum of all numbers from 1 till n can be calculated from (see eg here):
int sum(int n) {
return (n * (n+1)) / 2;
}
Note that n*(n+1) is an even number for any n, so using integer artihmetics for /2 is not an issue.
How does this help to get sum of numbers divisible by 3? Lets start with even numbers (divisble by 2). We write out the long form of the sum above:
1 + 2 + 3 + 4 + ... + n
multiply each term by 2:
2 + 4 + 6 + 8 + ... + 2*n
now I hope you see that this sum contains all numbers that are divisible by 2 up to 2*n. Those numbers are the first n numbers that are divisble by 2.
Hence, the sum of the fist n numbers that are divisble by 2 is 2 * sum(n). We can generalize that to write a function that returns the sum of the first n numbers that are divisble by m:
int sum_div_m( int n, int m) {
return sum(n) * m;
}
First I want to reproduce your inital example "up to 60 the sum is 870". For that we consider that
60/3 == 20 -> there are 20 numbers divisble by 3 and we get their sum from sum_div_m(20,3)
60/5 == 12 -> there are 12 numbers divisible by 5 and we get their sum from sum_div_m(12,5)
we cannot simply add the above two results because then we would count some numbers double. Those numbers are those divisible by 3 and 5, ie divisible by 15
60/15 == 4 -> there are 4 numbers divisble by 3 and 5 and we get their sum from sum_div_m(4,15).
Putting it together, the sum of all numbers divisible by 3 or 5 up to 60 is
int x = sum_div_m( 20,3) + sum_div_m( 12,5) - sum_div_m( 4,15);
Finally, back to your actual question:
But what if I want just the first 15 multiples?
Above we saw that there are
n == x/3 + x/5 - x/15
numbers that are divisble by 3 or 5 in the range 0...x. All division are using integer arithmetics. We already had the example of 60 with 20+12-4 == 28 divisble numbers. Another example is x=10 where there are n = 3 + 2 - 0 = 5 numbers divisible by 3 or 5 (3,5,6,9,10). We have to be a bit careful with integer arithmetics, but no big deal:
15*n == 5*x + 3*x - x
-> 15*n == 7*x
-> x == 15*n/7
Quick test: 15*28/7 == 60, looks correct.
Putting it all together the sum of the first n numbers divisible by 3 or 5 is
int sum_div_3_5(int n) {
int x = (15*n)/7;
return sum_div_m(x/3, 3) + sum_div_m(x/5, 5) - sum_div_m(x/15, 15);
}
To check that this is correct we can again try sum_div_3_5(28) to see that it returns 870 (because there are 28 numbers divisble by 3 or 5 up to 60 and that was the initial example).
PS Turned out that the question is really only about doing the maths. Though that isnt a big surprise. When you want to write efficient code you should primarily take care to use the right algorithm. Optimizations based on a given algorithm often are less effective than choosing a better algorithm. Once you chose an algorithm, often it does not pay off to try to be "clever" because compilers are much better at optimizing. For example this code:
int main(){
int x = 0;
int n = 60;
for (int i=0; i <= n; ++i) x += i;
return x;
}
will be be optimized by most compilers to a simple return 1830; when optimizations are turned on because compilers do know how to add all numbers from 1 to n. See here.
You can do it in compile time recursively by using class templates/meta functions if your value is known in compile time. So there will be no runtime cost.
Ex:
template<int n>
struct Sum{
static const int value = n + Sum<n-1>::value;
};
template<>
struct Sum<0>{
static constexpr int value = 0;
};
int main()
{
constexpr auto x = Sum<100>::value;
// x is known (5050) in compile time
return 0;
}

Fastest way to find dividers of a number in C++

I am trying to do an exercise in which you should find number of dividers of factorial of nth number:
https://www.e-olymp.com/en/problems/124
So here is my code:
int fact(int n){
return (n==1 || n==0) ? 1 : n*fact(n-1);
}
long long int a,b=1,c=0;
cin>>a;
long long int y=fact(a);
while(b!=y){
if(y%b==0){
c++;
}
b++;
}
cout<<c+1<<endl;
But this code takes too much time and I need something quicker. Don't give code, algorithm will be enough.
In this task 1 <= N <= 45. Obviously, N is too large to calculate it directly.
You should implement another approach. Just iterate from the 1 to N and do the prime factorization for every i, 1 < i <= N. Then you can easily find the prime factorization of N!, just merge factorization of every i, 1 < i <= N. After that calculate the total number of divisors using previously calculated factorization.
Example for 6!:
2 = 2
3 = 3
4 = 2 ^ 2
5 = 5
6 = 3 * 2
So:
6! = 2 ^ 4 * 3 ^ 2 * 5
And the number of divisors:
(4 + 1) * (2 + 1) * (1 + 1) = 30
Use a bit of mathematics.
If you know the prime factors of a number, it is trivial to calculate the number of divisors.
And it's easy to find the prime factors of a factorial. Without calculating the factorial itself.

Dynamic Programming solution for a Recursion solution

Given an input n , find the sum of all the possible combinations of numbers 1 ... n.
For example, if n=3 , then all the possible combinations are
(1),(2),(3),(1,2),(1,3),(2,3),(1,2,3)
and their sum is
1 + 2 + 3 + (1+2) + (1+3) + (2+3) + (1+2+3) =24
I am able to solve this problem using recursion. How can I solve this problem using Dynamic Programming ?
#include<iostream>
using namespace std;
int sum=0,n;
int f(int pos,int s)
{
if(pos>n)
{
return 0;
}
else
{
for(int i=pos+1;i<=n;++i)
{
sum+=s+i;
f(i,s+i);
}
}
}
int main()
{
cin>>n;
sum=0;
f(0,0);
cout<<sum<<'\n';
}
}
EDIT
Though this problem can be solved in constant time using this series.
But I want to know how this can be done using Dynamic Programming as I am very weak at it.
You do not need to use dynamic programming; you can use simple arithmetic if you want.
The number of cases is 2 ^ n, since each number is either on or off for a given sum.
Each number from 1 to n is used in exactly half of the sums, so each number comes 2 ^ (n-1) times.
1 + 2 + ... + n = (n - 1) * n / 2.
So the sum is (n - 1) * n / 2 * 2 ^ (n-1).
For n = 3, it is (4*3/2) * 4 = 24.
EDIT: if you really want to use dynamic programming, here's one way.
Dynamic programming makes use of saving the results of sub-problems to make the super problem faster to solve. In this question, the sub-problem would be the sum of all combinations from 1 ... n-1.
So create a mapping from n -> (number of combinations, sum of combinations).
Initialize with 1 -> (2,1). Because there are two combinations {0,1} and the sum is 1. Including 0 just makes the math a bit easier.
Then your iteration step is to use the mapping.
Let's say (n-1) -> (k,s), meaning there are k sets that sum to s for 1 ... n-1.
Then the number of sets for n is k * 2 (each combination either has n or does not).
And the sum of all combinations is s + (s + k * n), since you have the previous sum (where n is missing) plus the sum of all the combinations with n (which should be k * n more than s because there are k new combinations with n in each).
So add n -> (2*k,2*s + k*n).
And your final answer is the s in n -> (k,s).
let dp[n] be the result, Therefore:
dp[1] = 1
dp[n] = 2 * dp[n-1] + 2^(n-1) * n
First, it is obvious that dp[1] = 1
Second, dp[n] is the sum which contains n and sum which didn't contains n
E.G: dp[3] = {(1) (2) (1,2)} + {(3), (1,3), (2,3), (1,2,3)}
We can find dp[n-1] appear twice and the number of n appear 2^(n-1) times
I think maybe it is what you want.

uniformly distributed random number generation

Why does this code generates uniformly distributed numbers? I have some difficulties in understanding it. Could someone explain? Thanks.
int RandomUniform(int n) {
int top = ((((RAND_MAX - n) + 1) / n) * n - 1) + n;
int r;
do {
r = rand();
} while (r > top);
return (r % n);
}
update: I do understand why rand()%n doesn't give you a uniformly distributed sequence. My question is why the
top = ((((RAND_MAX - n) + 1) / n) * n - 1) + n;
What's the concern here? I think a simple top = RAND_MAX / n * n would do.
The function assumes that rand() is uniformly distributed; whether or not that is a valid assumption depends on the implementation of rand().
Given a uniform rand(), we can get a random number in the range [0,n) by calculating rand()%n. However, in general, this won't be quite uniform. For example, suppose n is 3 and RAND_MAX is 7:
rand() 0 1 2 3 4 5 6 7
rand() % n 0 1 2 0 1 2 0 1
We can see that 0 and 1 come up with a probability of 3/8, while 2 only comes up with a probability of 2/8: the distribution is not uniform.
Your code discards any value of rand() greater or equal to the largest multiple of n that it can generate. Now each value has an equal probability:
rand() 0 1 2 3 4 5 6 7
rand() % n 0 1 2 0 1 2 X X
So 0,1 and 2 all come up with a probability of 1/3, as long as we are not so unlucky that the loop never terminates.
Regarding your update:
I think a simple top = RAND_MAX / n * n would do.
If RAND_MAX were an exclusive bound (one more than the actual maximum), then that would be correct. Since it's an inclusive bound, we need to add one to get the exclusive bound; and since the following logic compares with > against an inclusive bound, then subtract one again after the calculation:
int top = ((RAND_MAX + 1) / n) * n - 1;
However, if RAND_MAX were equal to INT_MAX, then the calculation would overflow; to avoid that, subtract n at the beginning of the calculation, and add it again at the end:
int top = (((RAND_MAX - n) + 1) / n) * n - 1 + n;
The underlying problem is this: suppose you have a random number generator my_rand() that produces value from 0 to 6, inclusive, and you want to generate values from 0 to 5, inclusive; if you run your generator and return my_rand() % 6, you won't get a uniform distribution. When my_rand() returns 0, you get 0; when it returns 1, you get 1, etc. until my_rand() returns 6; in that case my_rand() % 6 is 0. So overall, my_rand() % 6 will return 0 twice as often as any other value. The way to fix this is to not use values greater than 5, that is, instead of my_rand() % 5 you write a loop and discard values from my_rand() that are too large. That's essentially what the code in the question is doing. I haven't traced it through, but the usual implementation is to compute the largest multiple of n that is less than or equal to RAND_MAX, and whenever rand() returns a value that's greater than that multiple, go back and get a new value.
I didn't trace through the code that computes top, but RAND_MAX is the largest value that rand() can return; (RAND_MAX + 1) / n * n would be a better ceiling, but if RAND_MAX is, say, INT_MAX, the result would be unpredictable. So maybe all that code is trying to avoid overflow.