How many digits are in N factorial - c++

I have the following problem, as says in the title: For each value of N, print out how many digits are in N!. For example, if n=32000, I should get 130271.
I have thought about a recursive solution. It works for smaller numbers, but for the above example it prints 31997. I am convinced that my thinking is wrong, but I can't really find a rule for bigger numbers. Somewhere, n! begins to skip steps, I think. I mean, it does not increases with a digit, but with two or three.
I have the following code:
#include <stdio.h>
#include <stdlib.h>
//For each value of N, print out how many digits are in N!.
int how_many(int n){
if( n <= 3)
return 1;
if( n == 4)
return 2;
if( n == 5 || n == 6)
return 3;
if( n >= 7)
return 1 + how_many(n-1);
}
int main()
{
int n;
printf("The number n is : ");
scanf("%d", &n);
int counter = 0;
counter = how_many(n);
printf("n! has %d digits", counter);
return 0;
}

What you're doing is really log10(N!). Once you realize that, you can use Stirling's Approximation or one of the other techniques explored here: https://math.stackexchange.com/questions/138194/approximating-log-of-factorial

The answer of #JohnZwinck solved my problem. Here is the resulting code:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define M_PI 3.14159265358979323846
//For each value of N, print out how many digits are in N!.
int digits_in_factorial(int n){
return floor((n+0.5)*log(n) - n+ 0.5*log(2*M_PI))/log(10) + 1;
}
int main()
{
int n;
printf("Numarul n este : ");
scanf("%d", &n);
int counter = 0;
counter = digits_in_factorial(n);
printf("n! are %d cifre", counter);
return 0;
}

OP's recursive method estimates too low:
return 1 + how_many(n-1);
Should be more like
return log10(n) + how_many(n-1);
Using OP's original integer approach and below how_many(32000) --> n! has 123560 digits - a better estimate.
int how_many(int n) {
if (n <= 3)
return 1;
if (n == 4)
return 2;
if (n == 5 || n == 6)
return 3;
int count = 0 + how_many(n - 1);
while (n > 3) {
n /= 10;
count++;
}
return count;
}
IAC, OP has found Stirling's method.

Related

How to print the b-th prime number coming after n?

I'm trying to write a c++ program which gets an integer n (n>=1 && n<=100000) from the user and puts the sum of its digits into b. The output needed is the b-th prime number coming after n. I'm an absolute beginner in programming so I don't know what's wrong with the for loop or any other code that it doesn't show the correct output. For example the 3rd prime number after 12 (1+2=3) is 19 but the loop counts the prime numbers from 2 instead of 12, so it prints 7 as result.
#include <iostream>
using namespace std;
bool isPrime(int n)
{
if(n <= 1)
return false;
for(int i = 2; i <= (n/2); i++)
if(n % i == 0)
return false;
return true;
}
int main()
{
long int n;
int b = 0;
cin>>n;
while(n >= 1 && n <= 100000){
b += n % 10;
n /= 10;
}
for(int i = n, counter = b; counter <= 10; i++)
if(isPrime(i)){
counter++;
if(i > n)
cout<<counter<<"th prime number after n is : "<<i<<endl;
}
return 0;
}
So one of the possible solutions to my question, according to #Bob__ answer (and converting it to the code style I've used in the initial code) is as follows:
#include <iostream>
using namespace std;
bool isPrime(long int number)
{
if(number <= 1)
return false;
for(int i = 2; i <= (number / 2); i++)
if(number % i == 0)
return false;
return true;
}
int sumOfDigits(long int number)
{
int sum = 0;
while(number >= 1 && number <= 100000)
{
sum += number % 10;
number /= 10;
}
return sum;
}
long int bthPrimeAfter(int counter, long int number)
{
while(counter)
{
++number;
if(isPrime(number))
--counter;
}
return number;
}
int main()
{
long int number;
cin>>number;
int const counter = sumOfDigits(number);
cout<<bthPrimeAfter(counter, number)<<"\n";
return 0;
}
As dratenik said in their comment:
You have destroyed the value in n to produce b in the while loop. When the for loop comes around, n keeps being zero.
That's a key point to understand, sometimes we need to make a copy of a variable. One way to do that is passing it to a function by value. The function argument will be a local copy which can be changed without affecting the original one.
As an example, the main function could be written like the following:
#include <iostream>
bool is_prime(long int number);
// ^^^^^^^^ So is `n` in the OP's `main`
int sum_of_digits(long int number);
// ^^^^^^^^^^^^^^^ This is a local copy.
long int nth_prime_after(int counter, long int number);
int main()
{
long int number;
// The input validation (check if it's a number and if it's in the valid range,
// deal with errors) is left to the reader as an exercise.
std::cin >> number;
int const counter = sum_of_digits(number);
std::cout << nth_prime_after(counter, number) << '\n';
return 0;
}
The definition of sum_of_digits is straightforward.
int sum_of_digits(long int number)
{
int sum = 0;
while ( number ) // Stops when number is zero. The condition n <= 100000
{ // belongs to input validation, like n >= 0.
sum += number % 10;
number /= 10; // <- This changes only the local copy.
}
return sum;
}
About the last part (finding the nth prime after the chosen number), I'm not sure to understand what the asker is trying to do, but even if n had the correct value, for(int i = n, counter = b; counter <= 10; i++) would be just wrong. For starters, there's no reason for the condition count <= 10 or at least none that I can think of.
I'd write something like this:
long int nth_prime_after(int counter, long int number)
{
while ( counter )
{
++number;
if ( is_prime(number) )
{
--counter; // The primes aren't printed here, not even the nth.
}
}
return number; // Just return it, the printing is another function's
} // responsabilty.
A lot more could be said about the is_prime function and the overall (lack of) efficiency of this algorithm, but IMHO, it's beyond the scope of this answer.

Improving optimization of nested loop

I'm making a simple program to calculate the number of pairs in an array that are divisible by 3 array length and values are user determined.
Now my code is perfectly fine. However, I just want to check if there is a faster way to calculate it which results in less compiling time?
As the length of the array is 10^4 or less compiler takes less than 100ms. However, as it gets more to 10^5 it spikes up to 1000ms so why is this? and how to improve speed?
#include <iostream>
using namespace std;
int main()
{
int N, i, b;
b = 0;
cin >> N;
unsigned int j = 0;
std::vector<unsigned int> a(N);
for (j = 0; j < N; j++) {
cin >> a[j];
if (j == 0) {
}
else {
for (i = j - 1; i >= 0; i = i - 1) {
if ((a[j] + a[i]) % 3 == 0) {
b++;
}
}
}
}
cout << b;
return 0;
}
Your algorithm has O(N^2) complexity. There is a faster way.
(a[i] + a[j]) % 3 == ((a[i] % 3) + (a[j] % 3)) % 3
Thus, you need not know the exact numbers, you need to know their remainders of division by three only. Zero remainder of the sum can be received with two numbers with zero remainders (0 + 0) and with two numbers with remainders 1 and 2 (1 + 2).
The result will be equal to r[1]*r[2] + r[0]*(r[0]-1)/2 where r[i] is the quantity of numbers with remainder equal to i.
int r[3] = {};
for (int i : a) {
r[i % 3]++;
}
std::cout << r[1]*r[2] + (r[0]*(r[0]-1)) / 2;
The complexity of this algorithm is O(N).
I've encountered this problem before, and while I don't find my particular solution, you could improve running times by hashing.
The code would look something like this:
// A C++ program to check if arr[0..n-1] can be divided
// in pairs such that every pair is divisible by k.
#include <bits/stdc++.h>
using namespace std;
// Returns true if arr[0..n-1] can be divided into pairs
// with sum divisible by k.
bool canPairs(int arr[], int n, int k)
{
// An odd length array cannot be divided into pairs
if (n & 1)
return false;
// Create a frequency array to count occurrences
// of all remainders when divided by k.
map<int, int> freq;
// Count occurrences of all remainders
for (int i = 0; i < n; i++)
freq[arr[i] % k]++;
// Traverse input array and use freq[] to decide
// if given array can be divided in pairs
for (int i = 0; i < n; i++)
{
// Remainder of current element
int rem = arr[i] % k;
// If remainder with current element divides
// k into two halves.
if (2*rem == k)
{
// Then there must be even occurrences of
// such remainder
if (freq[rem] % 2 != 0)
return false;
}
// If remainder is 0, then there must be two
// elements with 0 remainder
else if (rem == 0)
{
if (freq[rem] & 1)
return false;
}
// Else number of occurrences of remainder
// must be equal to number of occurrences of
// k - remainder
else if (freq[rem] != freq[k - rem])
return false;
}
return true;
}
/* Driver program to test above function */
int main()
{
int arr[] = {92, 75, 65, 48, 45, 35};
int k = 10;
int n = sizeof(arr)/sizeof(arr[0]);
canPairs(arr, n, k)? cout << "True": cout << "False";
return 0;
}
That works for a k (in your case 3)
But then again, this is not my code, but the code you can find in the following link. with a proper explanation. I didn't just paste the link since it's bad practice I think.

Rephrase pascal code to c++ so it can work as efficient as possible

So I got this task where I have pascal code and I need to get out whats the result. That wouldn't be a problem because I know pascal, but I need it to run in 1 second or less with numbers up to 10^9.
readln(N);
counter:=0;
for i:=N-1 downto 1 do begin
counter:= counter + 1;
if N mod i = 0 then break;
end;
writeln(counter);
Here is my code
#include <iostream>
using namespace std;
int main()
{
int x;
int counter = 0;
cin>>x;
for (int i = 2; i <= x; i++){
if (x % i == 0){
counter = x - x / i;
break;
}
}
cout<<counter;
return 0;
}
but it still cant quite get max score.
Restate problem:
1) Compute F = largest proper factor of X
2) Output X-F
Instead of directly searching for the largest proper factor, apply three trivial optimizations (maybe something more advanced will be needed, but first see if three trivial optimizations are enough).
A) Find S = smallest factor of X greater than 1. Output X-(X/S)
B) Special case for prime
C) Special case for even
int largest_proper_factor(int X)
{
if ( X % 2 == 0 ) return X/2; // Optimize even
// Note the add of .5 is only needed for non compliant sqrt version that
// might return a tiny fraction less than the exact answer.
int last = (int)(.5 + std::sqrt( (double) X )) );
for ( int i=3; i<=last; i+=2 ) // big savings here because even was optimized earlier
{
if ( X % i == 0 ) return X/i;
}
return 1; // special case for prime
}
Numbers like 10^9 usually indicate contest problems, which need creative thinking instead of fast CPU...
See, N mod i = 0 means N is divisible by i. So the loop counts numbers between N and one of its divisor (possibly plus one... Check it.) Which one — remains for you.
Ok i got the result i wanned:
#include <iostream>
using namespace std;
int main()
{
int x;
int counter = 0;
cin>>x;
for (int i = 2; i <= x; i++){
if (x % i == 0){
counter = x - x / i;
break;
}
if (x / 4 == i){
i = x - 1;
}
}
cout<<counter;
return 0;
}
Thank you everyone who helped me:)

How do you find multiplicity of a prime factor in a prime factorization of number?

I have to find multiplicity of smallest prime factor in all numbers till 10^7.I am using Sieve of Eratosthenes to find all the prime numbers. And there in a seperate array phi i am storing smallest prime factors of composite numbers.Here is my code for that
for(ull i=2;i<=m;i++)
{
if (check[i])
{
uncheck[i]=true;
for (ull k=i*i; k<=n; k+=i)
{
if(check[k]==true)
phi[k]=g;
check[k]=false;
}
}
}
Now i am running a loop till n and using a loop inside it to calculate it.
Here is code for that
for(ull i=4;i<=n;i++)
{
if(check[i]==false)
{
ull count=0;
ull l=i;
ull r=phi[i];
while(l%r==0)
{
l=l/r;
count++;
}
cout<<count<<'\n';
}
}
Is there any faster way to compute this?
Absolutely, you can do this without a loop.
c is probably at most 64 bits. It cannot contain any factor other than 1 more than 63 times. So instead of a loop, you write 63 nested if-statements.
For the case j == 2 your compiler may have some intrinsic functions that count trailing zero bits. If that is the case, then you handle that case separately and you need only 40 if's, because 3^41 > 2^64.
If you want to evaluate n such that jn = c, then recast the problem to
n = log(c) / log(j).
If n is an integer then your problem is solved.
Of course you need to consider floating point precision here; n might not be an exact integer, but close to one.
One alternative option, though not necessarily the most efficient, is to write a simple recursive function, such as this, assuming you are dealing with ints:
int recurseSubtract(int c, int j, int count){
if ((c==j)) {
return count + 1;
} else {
c = c-j;
subtract(c, j, count++);
}
}
int count = recurseSubtract(c,j,0);
However, see here for the pros and cons of loops vs. recursion.
Since you asked for the "multiplicity of smallest prime factor" you could easily use the same sieve approach to get multiplicity as you used to get the smallest factor.
for(ull i=2;i<=m;i++)
{
if (check[i])
{
uncheck[i]=true; // WHY??
ull k=i*i;
for (ull q=i; q<maxq; k=(q*=i))
for ( ; k<=n; k+=q)
{
if(check[k]==true)
phi[k]=g; // I copied 'g' from you, but didn't you mean 'i'?
if ( phi[k]==g )
count[k]++;
check[k]=false;
}
}
}
If you want to do a little better than that, the step of phi[k]==g and the some of the redundancy in check[k] access are needed only because q values are processed in forward sequence. It would be faster to work with q in reverse. Since q's are only easily computed in forward sequence and there are fairly few q's per i, the easiest way to process q backward would be to convert the loop over q into a recursive function (compute q on the way in and process it after the recursive call).
I found one simple rule but can not really describe in words. Here is another code calculating primenumbers
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
double f_power(double val, int exp);
int main(int argc,char* argv[]) {
int p[2];
int ctr = 0;
int ctr2 = 0;
int it_m = 0;
int it_1 = 0;
int it_2 = 0;
int it_c = 0;
int index = 3;
srand(time(NULL));
double t = clock();
double s = clock();
int prime = 2;
FILE *file;
file = fopen("ly_prime.txt", "w");
//f_power(2.0, 57885161)
for (it_m = 2; it_m <= 2000; it_m++) {
for (it_1 = it_m, ctr2 = 0, it_c = it_m; it_1 >= 2; it_1--) {
for (it_2 = it_1; it_2 >= 2; it_2--) {
if (it_1 * it_2 - it_c == 0) {
p[ctr % 2] = it_c;
if (ctr >= 1 && p[ctr % 2] - p[(ctr - 1) % 2] == 2) {
//prime[0] = (p[ctr % 2] - 1);
prime = (p[ctr % 2] - 1);
fprintf(stdout, "|%d _ i: %d _ %d\n", isPrime(prime),index, prime);
index++;
}
ctr++;
}
}
}
}
t = clock() - t;
fprintf(file, "|%d_ %d_ %d ", prime, index - 2, ctr);
}
double f_power(double val, int exp) {
int i = 0;
double help = val;
for(i = 1; i < exp; i++) {
val *= help;
}
return val;
}
int isPrime(int number)
{
int i = 2;
for(i=2; i < number; i++)
{
int leftOver=(number % i);
if (leftOver==0)
{
return 1;
break;
}
}
return 0;
}
perhaps it helps understanding, best regards

Recursive function to check digits

Write a recursive function to check how many digits in the number can be divided by the digit which is after them. Example: 84963 should return 2, because 8 can be divided by 4 and 6 can be divided by 3. My function doesnt seem to output anything at all.
#include <iostream>
using namespace std;
int fun (int n);
int main()
{
int n;
cin >> n;
cout << fun(n) << endl;
return 0;
}
int fun(int n){
int count = 0;
if (fun(n % 100) % fun(n % 10) == 0)
count++;
return count;
}
Your recursion does not make much sense at the moment. A more logical approach to this would be to see if the last number (so 1 in 321), can currently divide the second last number (so 2 in 321). You could do this by defining a function that checks if that is possible, and recursively passes on the number divided by 10. That function would look something like this:
int fun(int n)
{
if (n < 10)
return 0;
int last = n % 10;
n = n / 10;
int secondlast = n % 10;
if (secondlast != 0 && last != 0 && secondlast % last == 0)
return 1 + fun(n);
else
return fun(n);
}
Update note: After looking into Vlad from moscow's comment, I moved the last != 0 part of the condition forward, to solve a bug (divide by 0).
The problem Vlad from moscow was talking about is the following: If you want, for example, the part 04 to count as 0, you should use the code as it is above. Otherwise you should remove the secondlast != 0 part.
int countIfDiv(int num) {
int pair = num % 100;
int first = pair / 10;
if (first == 0) return 0;
int second = pair % 10;
int next = num / 10;
return first % second == 0 ? 1 + countIfDiv(next) : 0 + countIfDiv(next);
}
Just pull a pair, try the division, then chop the last number and repeat.
You're not actually updating n value so you get into an infinite loop, on the other hand, your function is, initially, only designed for 3 digits number. I think that it should be something similar to:
int fun(int n, int ant, int count){
if( n == 0 )
return count;
if (ant != 0 &&
(n%10) % ant == 0)
count++;
return fun(n/10, n%10, count);
}
I should work with different number of digits.
The valid code will be
size_t fun( int n )
{
const int base = 10;
int digit = n % base;
n /= base;
return ( n == 0 ?
0 :
( digit && n % base && !( n % base % digit ) ) + fun( n ) );
}