I have a homework that count total zero in n factorial. What should i do?
I only find way to count trailing of factorial
static int findTrailingZeros(int n)
{
// Initialize result
int count = 0;
// Keep dividing n by powers
// of 5 and update count
for (int i = 5; n / i >= 1; i *= 5)
count += n / i;
return count;
}
The total number of zeros in n! is given by sequence A027869 in the On-line Encyclopedia of Integer Sequences. There really seems to be no way to compute the total number of zeros in n! short of computing n! and counting the number of zeros. With a big int library, this is easy enough. A simple Python example:
import math
def zeros(n): return str(math.factorial(n)).count('0')
So, for example, zeros(100) evaluates to 30. For larger n you might want to skip the relatively expensive conversion to a string and get the 0-count arithmetically by repeatedly dividing by 10.
As you have noted, it is far easier to compute the number of trailing zeros. Your code, in Python, is essentially:
def trailing_zeros(n):
count = 0
p = 5
while p <= n:
count += n//p
p *= 5
return count
As a heuristic way to estimate the total number of zeros, you can first count the number of trailing zeros, subtract that from the number of digits in n!, subtract an additional 2 from this difference (since neither the first digit of n! nor the final digit before the trailing zeros are candidate positions for non-trailing zeros) and guess that 1/10 of these digits will in fact be zeros. You can use Stirling's formula to estimate the number of digits in n!:
def num_digits(n):
#uses Striling's formula to estimate the number of digits in n!
#this formula, known as, Kamenetsky's formula, gives the exact count below 5*10^7
if n == 0:
return 1
else:
return math.ceil(math.log10(2*math.pi*n)/2 + n *(math.log10(n/math.e)))
Hence:
def est_zeros(n):
#first compute the number of candidate postions for non-trailing zerpos:
internal_digits = max(0,num_digits(n) - trailing_zeros(n) - 2)
return trailing_zeros(n) + internal_digits//10
For example est_zeros(100) evaluates to 37, which isn't very good, but then there is no reason to think that this estimation is any better than asymptotic (though proving that it is asymptotically correct would be very difficult, I don't actually know if it is). For larger numbers it seems to give reasonable results. For example zeros(10000) == 5803 and est_zeros == 5814.
How about this then.
count = 0
s = str(fact)
for i in s:
if i=="0":
count +=1
print(count)
100! is a big number:
100! = 93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000
To be more precise it need ~525 bit and can not be computed without some form of bigint math.
However trailing zeros might be computable on normal integers:
The idea is to limit the result to still fit into your data type. So after each iteration test if the result is divisible by 10. If it is increment your zeros counter and divide the result by 10 while you can. The same goes for any primes except those that divide 10 so not: 2,5 (but without incrementing your zeros counter). This way you will have small sub-result and count of trailing zeros.
So if you do a 2,5 factorization of all the multiplicants in n! the min of the both exponents of 2,5 will be the number of trailing zeros as each pair produces one zero digit (2*5 = 10). If you realize that exponent of 5 is always smaller or equal than exponent of 2 its enough to do the factorization of 5 (just like you do in your updated code).
int fact_trailing_zeros(int n)
{
int i,n5;
for (n5=0,i=5;n>=i;i*=5) n5+=n/i;
return n5;
}
With results:
Trailing zeors of n!
10! : 2
100! : 24
1000! : 249
10000! : 2499
100000! : 24999
1000000! : 249998
10000000! : 2499999
100000000! : 24999999
[ 0.937 ms]
However 100! contains also non trailing zeros and to compute those I see no other way than compute the real thing on a bigint math ... but that does not mean there is no workaround like for trailing zeros...
If it helps here are computed factorials up to 128! so you can check your results:
Fast exact bigint factorial
In case n is bounded to small enough value you can use LUT holding all the factorials up to the limit as strings or BCD and just count the zeros from there... or even have just the final results as a LUT ...
Here some bad code, but it works. You have to use TrailingZeros() only
public static int TrailingZeros(int n)
{
var fac = Factorial(n);
var num = SplitNumber(fac);
Array.Reverse(num);
int i = 0;
int res = 0;
while (num[i] == 0)
{
if (num[i] == 0)
{
res++;
}
i++;
}
return res;
}
public static BigInteger Factorial(int number)
{
BigInteger factorial = 1; // значение факториала
for (int i = 2; i <= number; i++)
{
factorial = factorial * i;
}
return factorial;
}
public static int[] SplitNumber(BigInteger number)
{
var result = new int[0];
int count = 0;
while (number > 0)
{
Array.Resize(ref result, count + 1);
result[count] = (int)(number % 10);
number = number / 10;
count++;
}
Array.Reverse(result);
return result;
}
Related
Problem Statement: The Fibonacci word sequence of bit strings is defined as:
F(0) = 0, F(1) = 1
F(n − 1) + F(n − 2) if n ≥ 2
For example : F(2) = F(1) + F(0) = 10, F(3) = F(2) + F(1) = 101, etc.
Given a bit pattern p and a number n, how often does p occur in F(n)?
Input:
The first line of each test case contains the integer n (0 ≤ n ≤ 100). The second line contains the bit
pattern p. The pattern p is nonempty and has a length of at most 100 000 characters.
Output:
For each test case, display its case number followed by the number of occurrences of the bit pattern p in
F(n). Occurrences may overlap. The number of occurrences will be less than 2^63.
Sample input: 6 10 Sample output: Case 1: 5
I implemented a divide and conquer algorithm to solve this problem, based on the hints that I found on the internet: We can think of the process of going from F(n-1) to F(n) as a string replacement rule: every '1' becomes '10' and '0' becomes '1'. Here is my code:
#include <string>
#include <iostream>
using namespace std;
#define LL long long int
LL count = 0;
string F[40];
void find(LL n, char ch1,char ch2 ){//Find occurences of eiher "11" / "01" / "10" in F[n]
LL n1 = F[n].length();
for (int i = 0;i+1 <n1;++i){
if (F[n].at(i)==ch1&&F[n].at(i+1)==ch2) ++ count;
}
}
void find(char ch, LL n){
LL n1 = F[n].length();
for (int i = 0;i<n1;++i){
if (F[n].at(i)==ch) ++count;
}
}
void solve(string p, LL n){//Recursion
// cout << p << endl;
LL n1 = p.length();
if (n<=1&&n1>=2) return;//return if string pattern p's size is larger than F(n)
//When p's size is reduced to 2 or 1, it's small enough now that we can search for p directly in F(n)
if (n1<=2){
if (n1 == 2){
if (p=="00") return;//Return since there can't be two subsequent '0' in F(n) for any n
else find(n,p.at(0),p.at(1));
return;
}
if (n1 == 1){
if (p=="1") find('1',n);
else find('0',n);
return;
}
}
string p1, p2;//if the last character in p is 1, we can replace it with either '1' or '0'
//p1 stores the substring ending in '1' and p2 stores the substring ending in '0'
for (LL i = 0;i<n1;++i){//We replace every "10" with 1, "1" with 0.
if (p[i]=='1'){
if (p[i+1]=='0'&&(i+1)!= n1){
if (p[i+2]=='0'&&(i+2)!= n1) return;//Return if there are two subsequent '0'
p1.append("1");//Replace "10" with "1"
++i;
}
else {
p1.append("0");//Replace "1" with "0"
}
}
else {
if (p[i+1]=='0'&&(i+1)!= n1){//Return if there are two subsequent '0'
return;
}
p1.append("1");
}
}
solve(p1,n-1);
if (p[n1-1]=='1'){
p2 = p1;
p2.back() = '1';
solve(p2,n-1);
}
}
main(){
F[0] = "0";F[1] = "1";
for (int i = 2;i<38;++i){
F[i].append(F[i-1]);
F[i].append(F[i-2]);
}//precalculate F(0) to F(37)
LL t = 0;//NumofTestcases
int n; string p;
while (cin >> n >> p) {
count = 0;
solve(p,n);
cout << "Case " << ++t << ": " << count << endl;
}
}
The above program works fine, but with small inputs only. When i submitted the above program to codeforces i got an answer wrong because although i shortened the pattern string p and reduces n to n', the size of F[n'] is still very large (n'>=50). How can i modify my code to make it works in this case, or is there another approach (such as dynamic programming?). Many thanks for any advice.
More details about the problem can be found here: https://codeforces.com/group/Ir5CI6f3FD/contest/273369/problem/B
I don't have time now to try to code this up myself, but I have a suggested approach.
First, I should note, that while that hint you used is certainly accurate, I don't see any straightforward way to solve the problem. Perhaps the correct follow-up to that would be simpler than what I'm suggesting.
My approach:
Find the first two ns such that length(F(n)) >= length(pattern). Calculating these is a simple recursion. The important insight is that every subsequent value will start with one of these two values, and will also end with one of them. (This is true for all adjacent values -- for any m > n, F(m) will begin either with F(n) or with F(n - 1). It's not hard to see why.)
Calculate and cache the number of occurrences of the pattern in this these two Fs, but whatever index shifting technique makes sense.
For F(n+1) (and all subsequent values) calculate by adding together
The count for F(n)
The count for F(n - 1)
The count for those spanning both F(n) and F(n - 1). We can achieve that by testing every breakdown of pattern into (nonempty) prefix and suffix values (i.e., splitting at every internal index) and counting those where F(n) ends in prefix and F(n - 1) starts with suffix. But we don't have to have all of F(n) and F(n - 1) to do this. We just need the tail of F(n) and the head of F(n - 1) of the length of the pattern. So we don't need to calculate all of F(n). We just need to know which of those two initial values our current one ends with. But the start is always the predecessor, and the end oscillates between the previous two. It should be easy to keep track.
The time complexity then should be proportional to the product of n and the length of the pattern.
If I find time tomorrow, I'll see if I can code this up. But it won't be in C -- those years were short and long gone.
Collecting the list of prefix/suffix pairs can be done once ahead of time
I have a C code off finding large perfect numbers below,
#include <stdio.h>
int main ()
{
unsigned long long num,i,sum;
while (scanf ("%llu",&num) != EOF && num)
{
sum = 1;
for (i=2; i*i<=num; i++)
{
if (num % i == 0)
{
if (i*i == num)
sum += i;
else
sum += (i + num/i);
}
}
if (sum == num)
printf ("Perfect\n");
else if (sum > num)
printf ("Abundant\n");
else
printf ("Deficient\n");
}
return 0;
}
I tried to find whether a number is perfect, abundant or deficient. I run a loop upto the square root of numto minimize the runtime. It works fine <= 10^15 but for the larger values it takes too long time to execute.
For example,for the following input sets,
8
6
18
1000000
1000000000000000
0
this code shows the following outputs,
Deficient
Perfect
Abundant
Abundant
Abundant
But, for 10^16 it doesn't respond quickly.
So, is there any better way to find a perfect number for too long values? Or is there any better algorithm to implement here??? :)
Yes, there is a better algorithm.
Your algorithm is basically the simple one--adding up the divisors of a number to find... the sum of the divisors of a number (excluding itself). But you can use the number-theoretic formula for finding the sum of the divisors of a number (including itself). If the prime numbers dividing n are p1, p2, ..., pk and the powers of those primes in the canonical decomposition of n are a1, a2, ..., ak, then the sum of the divisors of n is
(p1**(a1+1) - 1) / (p1 - 1) * (p2**(a2+1) - 1) / (p2 - 1) * ...
* (pk**(ak+1) - 1) / (pk - 1)
You can find the prime divisors and their exponents more quickly than finding all the divisors of n. Subtract n from that expression above and you get the sum you want.
There are some tricks, of course, to find the pis and ais more efficiently: I'll leave that to you.
By the way, if your purpose is just to find the perfect numbers, as in your title, you would do better to use Euclid's formula for even prime numbers. Find the Mersenne prime numbers by examining all 2**p-1 for prime p to see if they are prime--there are shortcuts to doing this as well--then constructing a perfect number from that Mersenne prime. This would leave out any odd perfect numbers, though. If you find any, let the mathematical community know--that would make you world famous.
Of course, the fastest way of all to find perfect numbers is to use the lists already made of some of them.
It is a matter of factorization of numbers. You can read more here: https://en.wikipedia.org/wiki/Integer_factorization
Unfortunately no good news for you - the bigger the number gets, the longer it takes.
To start with your code, try not to multiply i*i each iteration.
Instead of:
for (i=2; i*i<=num; i++)
calculate square root of num first, and then compare
i <= square_root_of_num in the loop.
// Program to determine whether perfect or not
# include <bits/stdc++.h>
using namespace std;
map<long long int, int> mp; // to store prime factors and there frequency
void primeFactors(long long int n)
{
// counting the number of 2s that divide n
while (n%2 == 0)
{
mp[2] = mp[2]+1;
n = n/2;
}
long long int root = sqrt(n);
// n must be odd at this point. So we can skip every even numbers next
for (long long int i = 3; i <= root; i = i+2)
{
// While i divides n, count frequency of i prime factor and divide n
while (n%i == 0)
{
mp[i] = mp[i]+1;
n = n/i;
}
}
// This condition is to handle the case whien n is a prime number
// greater than 2
if (n > 2)
{
mp[n] = mp[n]+1;
}
}
long long int pow(long long int base, long long int exp)
{
long long int result = 1;
base = base;
while (exp>0)
{
if (exp & 1)
result = (result*base);
exp >>= 1;
base = (base*base);
}
return result;
}
int main ()
{
long long num, p, a, sum;
while (scanf ("%lld",&num) != EOF && num)
{
primeFactors(num);
sum = 1;
map<long long int, int> :: iterator i;
for(i=mp.begin(); i!=mp.end(); i++)
{
p = i->first;
a = i->second;
sum = sum*((pow(p,a+1)-1)/(p-1));
}
if (sum == 2*num)
printf ("Perfect\n");
else if (sum > num)
printf ("Abundant\n");
else
printf ("Deficient\n");
mp.clear();
}
return 0;
}
I want to solve a mathematical problem in a fastest possible way.
I have a set of natural numbers between 1 to n, for example {1,2,3,4,n=5} and I want to calculate a formula like this:
s = 1*2*3*4+1*2*3*5+1*2*4*5+1*3*4*5+2*3*4*5
as you can see, each element in the sum is a multiplications of n-1 numbers in the set. For example in (1*2*3*4), 5 is excluded and in (1*2*3*5), 4 is excluded. I know some of the multiplications are repeated, for example (1*2) is repeated in 3 of the multiplications. How can I solve this problem with least number of multiplications.
Sorry for bad English.
Thanks.
Here is a way that does not "cheat" by replacing multiplication with repeated addition or by using division. The idea is to replace your expression with
1*2*3*4 + 5*(1*2*3 + 4*(1*2 + 3*(1 + 2)))
This used 9 multiplications for the numbers 1 through 5. In general I think the multiplication count would be one less than the (n-1)th triangular number, n * (n - 1) / 2 - 1. Here is Python code that stores intermediate factorial values to reduce the number of multiplications to just 6, or in general 2 * n - 4, and the addition count to the same (but half of them are just adding 1):
def f(n):
fact = 1
term = 2
sum = 3
for j in range(2, n):
fact *= j
term = (j + 1) * sum
sum = fact + term
return sum
The only way to find which algorithm is the fastest is to code all of them in one language, and run each using a timer.
The following would be the most straightforward answer.
def f(n):
result = 0
nList = [i+1 for i in range(n)]
for i in range(len(nList)):
result += reduce(lambda x, y: x*y,(nList[:i]+nList[i+1:]))
return result
Walkthrough - use the reduce function to multiply all list's of length n-1 and add to the variable result.
If you just want to minimise the number of multiplications, you can replace all the multiplications by additions, like this:
// Compute 1*2*…*n
mult_all(n):
if n = 1
return 1
res = 0
// by adding 1*2*…*(n-1) an entirety of n times
for i = 1 to n do
res += mult_all(n-1)
return res
// Compute sum of 1*2*…*(i-1)*(i+1)*…*n
sum_of_mult_all_but_one(n):
if n = 1
return 0
// by computing 1*2*…*(n-1) + (sum 1*2*…*(i-1)*(i+1)*…*(n-1))*n
res = mult_all(n-1)
for i = 1 to n do
res += sum_of_mult_all_but_one(n-1)
return res
Here is an answer that would work with javascript. It is not the fastest way because it is not optimized, but it should work if you want to just find the answer.
function combo(n){
var mult = 1;
var sum = 0;
for (var i = 1; i <= n; i++){
mult = 1;
for (var j = 1; j<= n; j++){
if(j != i){
mult = mult*j;
}
}
sum += mult;
}
return (sum);
}
alert(combo(n));
How does one, computationally and dynamically, derive the 'ths' place equivalent of a whole integer? e.g.:
187 as 0.187
16 as 0.16
900041 as 0.900041
I understand one needs to compute the exact th's place. I know one trick is to turn the integer into a string, count how many places there are (by how many individual characters there are) and then create our future value to multiply against by the tenth's value derived - like how we would on pen and paper - such as:
char integerStr[7] = "186907";
int strLength = strlen(integerStr);
double thsPlace = 0.0F;
for (int counter = 0; counter < strLength; ++counter) {
thsPlace = 0.1F * thsPlace;
}
But what is a non-string, arithmetic approach to solving this?
pseudocode:
n / pow(10, floor(log10(n))+1)
Divide the original value by 10 repeatedly until it's less than one:
int x = 69105;
double result = (double) x;
while (x > 1.0) x /= 10.0;
/* result = 0.69105 */
Note that this won't work for negative values; for those, you need to perform the algorithm on the absolute value and then negate the result.
[edited for strange indenting]
I'm not sure exactly what you mean with your question, but here's what I would do:
int placeValue(int n)
{
if (n < 10)
{
return 1;
}
else
{
return placeValue(n / 10) + 1;
}
}
[This is a recursive method]
I don't know how performant the pow(10, x) version is, but you could try to do most of this with integer arithmetic. Assuming we are only dealing with positive values or 0 (use the absolute value, if necessary):
int divisor = 1;
while (divisor < x)
divisor *= 10;
if (divisor > 0)
return (double)x / divisor;
Note that the above needs some safeguards, i.e. checking if divisor may have overflow (in that case, it would be negative), if x is positive, etc. But I assume you can do that yourself.
Given the number 654 the check sum is 7.
The check sum is calculated by splitting the numbers into individual digits, and calculating the bitwise XOR sum for all digits.
A limitation is that no digit larger than 7 is allowed, in effect making them octal numbers.
And here's a JavaScript implementation
function (numberString) {
var sum = 0;
var digits = numberString.split('');
for (var i=0; i < digits.length; i++) {
var digit = parseInt(digits[i]);
sum = sum ^ digit;
}
return sum;
};
My question is: Does this "method"/"system" have a name/history, similar to the Luhn algorithm? (Even though this is far simpler)