How to find out how many times the prime number occurs? - c

I need to write a program to input a number and output it's factorial in the form in C
4!=(2^3)*(3^1)
5!=(2^3)*(3^1)*(5^1)
I am able to find the prime numbers 2, 3 and 5 but how do i figure out how many times they occur? (^3, ^1, ^1)
Code:
int main() {
int num,i,count,n;
printf("Enter to find prime numbers: ");
scanf("%d",&n);
for(num = 2; num<=n;num++) {
count = 0;
for(i=2;i<=num/2;i++) {
if(num%i==0)
{
count++;
break;
}
}
if(count==0 && num!= 1)
printf("%d ",num);
}
return 0;
}

Without going into any code, Ill explain what the problem in the way you are doing things ...
Let us say you want to find the prime factors of the factorial of 5. So you do:
5! = 2 x 3 x 4 x 5 (this is your outer loop (for(num = ...)
Let us say that for a particular iteration, num = 4. Then, you have another iteration in i that checks of each number upto that num/2 is a factor. Now for a small value of 5! this is not a problem. Consider a bigger number like 25!. In this case, your outer loop will be:
25! = 1 x 2 x 3 x ... 22 x 23 x 24 x 25
Now your outer iteration num goes much further. Consider now the number 24. 24/2 = 12. Your program is going to print all factors that divide 24 upto 12, which happen to be 2, 3, 4, 6, and 12. I am sure, that is not what you want.
First, do not attempt to find the factorial for large numbers. You will run into overflow issues. Next, Ill give you some pointers and hope you can solve the problem on your own. Its a very cool problem, so I really hope you are able to solve it:
Study the prime sieve algorithm (http://en.wikipedia.org/wiki/Sieve_of_Eratosthenes). You will not be using this directly, but only the ideas mentioned here.
Create two arrays. The first one will contain the prime factors, while the next one will contain the total count of the factors occuring in the factorial.
For a particular num u need to be iterating not using the i that you have used but using the values in your prime array.
3.1. Use the method explained by Barmar to find the number of times this num is divisible by the factors, and update the corresponding counts in the count array.
Print out the factors and counts that you have obtained.
Finally, I think its a pretty good question. It teaches you how to not run into overflow errors and still be able to solve problem using the computer. It can teach you dynamic memory allocation and memory management skills, if that is the way you want to go. It also helps you to think critically about a problem. You dont deserve a -1. I have increased your rating.
Have fun programming, and keep thinking critically about each setp in your program.
Cheers!

for(num = 2; num<=n; ++num){
count = 0;
while(n % num == 0){
n /= num;
++count;
}
if(count!=0)
printf("(%d^%d)", num, count);
}

Related

Why I am getting TLE on Lightoj 1176 problem?

Problem: Ekka and his friend Dokka decided to buy a cake. They both love cakes and that's why they want to share the cake after buying it. As the name suggested that Ekka is very fond of odd numbers and Dokka is very fond of even numbers, they want to divide the cake such that Ekka gets a share of N square centimeters and Dokka gets a share of M square centimeters where N is odd and M is even. Both N and M are positive integers.
They want to divide the cake such that N * M = W, where W is the dashing factor set by them. Now you know their dashing factor, you have to find whether they can buy the desired cake or not.
Input
Input starts with an integer T (≤ 10000), denoting the number of test cases.
Each case contains an integer W (2 ≤ W < 2^63). And W will not be a power of 2.
Output
For each case, print the case number first. After that print "Impossible" if they can't buy their desired cake. If they can buy such a cake, you have to print N and M. If there are multiple solutions, then print the result where M is as small as possible
Time Limit: 2 second(s)
I've tried on sample inputs and got same result as the output.
Sample Input
3
10
5
12
Output for Sample Input
Case 1: 5 2
Case 2: Impossible
Case 3: 3 4
My code:
#include<stdio.h>
#include<math.h>
int main()
{
int t,k;
scanf("%d",&t);
for(k=1;k<=t;k++)
{
int a,i,j=1,c;
scanf("%d",&a);
for(i=2;i<sqrt(a)+2;i++)
{
if(a%i==0 && i%2!=0)
c=i;
}
int b=a/c;
if(b%2==0 && b*c==a)
printf("Case %d: %d %d\n",k,c,b);
else
printf("Case %d: Impossible\n",k);
}
return 0;
}
The Light OJ given TLE to my solution.
Your solution is giving TLE.
May be you need to optimise it a little.
One thing I am suggesting is:
If the number W is not divisible by 2, print "Impossible".
If the number W is divisible by 2, keep dividing the number by 2, until it becomes an odd number.
So, the odd number generated will be one share and W/odd_number will be other share.

Minimum Size Subarray Sum with sorting

The Minimum Size Subarray Sum problem:
given an array of n positive integers and a positive integer s, find the minimal length of a subarray of which the sum ≥ s. If there isn't one, return 0 instead.
For example, given the array [2,3,1,2,4,3] and s = 7,
the subarray [4,3] has the minimal length under the problem constraint.
The following is my solution:
public int minSubArrayLen(int s, int[] nums) {
long sum = 0;
int a = 0;
if (nums.length < 1)
return 0;
Arrays.sort(nums);
for (int i = nums.length-1; i >= 0; i--) {
sum += nums[i];
a++;
if (sum>=s)
break;
}
if (sum < s) {
return 0;
}
return a;
}
This solution was not accepted because it did not pass the following test case:
697439
[5334,6299,4199,9663,8945,3566,9509,3124,6026,6250,7475,5420,9201,9501,38,5897,4411,6638,9845,161,9563,8854,3731,5564,5331,4294,3275,1972,1521,2377,3701,6462,6778,187,9778,758,550,7510,6225,8691,3666,4622,9722,8011,7247,575,5431,4777,4032,8682,5888,8047,3562,9462,6501,7855,505,4675,6973,493,1374,3227,1244,7364,2298,3244,8627,5102,6375,8653,1820,3857,7195,7830,4461,7821,5037,2918,4279,2791,1500,9858,6915,5156,970,1471,5296,1688,578,7266,4182,1430,4985,5730,7941,3880,607,8776,1348,2974,1094,6733,5177,4975,5421,8190,8255,9112,8651,2797,335,8677,3754,893,1818,8479,5875,1695,8295,7993,7037,8546,7906,4102,7279,1407,2462,4425,2148,2925,3903,5447,5893,3534,3663,8307,8679,8474,1202,3474,2961,1149,7451,4279,7875,5692,6186,8109,7763,7798,2250,2969,7974,9781,7741,4914,5446,1861,8914,2544,5683,8952,6745,4870,1848,7887,6448,7873,128,3281,794,1965,7036,8094,1211,9450,6981,4244,2418,8610,8681,2402,2904,7712,3252,5029,3004,5526,6965,8866,2764,600,631,9075,2631,3411,2737,2328,652,494,6556,9391,4517,8934,8892,4561,9331,1386,4636,9627,5435,9272,110,413,9706,5470,5008,1706,7045,9648,7505,6968,7509,3120,7869,6776,6434,7994,5441,288,492,1617,3274,7019,5575,6664,6056,7069,1996,9581,3103,9266,2554,7471,4251,4320,4749,649,2617,3018,4332,415,2243,1924,69,5902,3602,2925,6542,345,4657,9034,8977,6799,8397,1187,3678,4921,6518,851,6941,6920,259,4503,2637,7438,3893,5042,8552,6661,5043,9555,9095,4123,142,1446,8047,6234,1199,8848,5656,1910,3430,2843,8043,9156,7838,2332,9634,2410,2958,3431,4270,1420,4227,7712,6648,1607,1575,3741,1493,7770,3018,5398,6215,8601,6244,7551,2587,2254,3607,1147,5184,9173,8680,8610,1597,1763,7914,3441,7006,1318,7044,7267,8206,9684,4814,9748,4497,2239]
The expected answer is 132 but my output was 80.
Does anyone have any idea what went wrong with my algorithm/code?
I will simply explain the flaw in the logic rather giving the correct logic to handle the problem statement
You are taking the numbers in a specific sequence and then adding them for comparison. Quite easily the case can be different where you take numbers in random order to get the exact sum.
For example [2,3,1,2,4,3] and s = 7.
Based on your logic
Step 1-> Sort the numbers and you get [1,2,2,3,3,4]
Step 2-> You pick last 2 number (3,4) to get your sum 7
Lets change the sum to 8
From Step 2-> You get 3+3+4 = 10 so u break out of the loop. After this step you return a = 2
Flaw here is 4+3+1 also makes 8 something your logic skips.
Same way 3+3+2 is also possible solution to achieve 8.
You sorting the array is first flaw in the logic itself. If you consider subarray of existing arrangement, sorting changes the arrangement therefore you will never be able to get the expected solution.

Is there a way to find the 2 whole factors of an int that are closest together?

I'm a beginner still learning to us C and I don't know how to find the factors of an int that are the closest to each other.
For example, if the input was the number 6, the output would be [2,3]. If the input was 24, then the output would be [4,6].
Is there a way to do this? Any help would be appreciated.
The algorithm to do this is simple; take the square root of your number as an integer (you want to truncate, not round). Test if that value is a factor of your input; if so, your input divided by that number are your answer. Otherwise, subtract 1 from your previous value and try again.
In code (the array literal is the wrong syntax, but the theory is correct):
//this code assumes that your input is > 0, will not work otherwise
function int[] getClosestFactors(int input) {
int testNum = (int)sqrt(input);
while (input % testNum != 0) {
testNum--;
}
return {testNum, input / testNum};
}
Basically, you know that in any pair of factors, the lowest factor must be less than or equal to the square root. So if you start at the integer equal to or less than the square root of your input, and count down, the first factor you find will be the smaller of the pair of closest factors. This terminates for all integers > 0 because you will eventually reach 1, which is a factor of all other numbers.

Find Prime Number 10001 Optimization Questions

So I have created a program that finds the 10,001st prime number. Here is the main for that program:
int main(){
int i;
int j;
int count=0;
int currnumber=0;
for(i=1; count < 10002; i++){
if(isPrime(i)){
count++;
currnumber = i;
if(count == 10002)
printf("%i",currnumber);
}
}
}
And here is the code for the IsPrime function I built in a custom library:
long long isPrime(long long number){
long long i = 2;
if(number == 2)
return 1;
for(i=2;i<number;i++){
if(number % i == 0)
return 0;
}
if(i >= number && ((number % 1 == 0) && (number % number == 0)))
return 1;
}
When I run the program, it works and gives me the correct answer(It's an Euler problem so I know i did it right :D), but it takes at least 6 seconds to process. So my questions are:
Why is it taking that long? Is it something to do with how i've set my algorithm?
How can I potentially improve my code to make it run faster?
Thanks in advance!
Probably the first thing you can do is cache the prime number values you do create, and use the sieve of eratosthenes algorithm in order to not have to constantly recalculate prime number values once you've found them.
You are using two for loops
A faster way which comes to my mind and is also a great exercise is the algorithm called: Sieve of Eratosthenes
There's a lot of optimisations that can be done. A few people have mentioned the sieve of Eratosthenes, which is right, but let me give you some additional pointers.
Improving your code without changing algorithm: As Michael Parker mentioned, you do not need to deal with the even numbers because only one of them is prime (the number 2, which makes it the 'oddest' prime of all -- that's a pun). You can do a similar trick by avoiding multiples of three, which boils down to only dealing with integers i which are either 1 or 5 more than a multiple of 6. To turn that into code, first set count to 3 to account for primes 2, 3, and 5. Then start i at 6 and test both i+1 and i+5 (both within the for loop), and then increment i by 6 every time.
For isPrime() you could add similar improvements but you can also stop trial dividing once you reach the square root of the number. This is because a number has a divisor >= sqrt(number) if and only if it has a divisor <= sqrt(number). To prove this, the key is that if a divides number, then number/a is another divisor (you can fill in remaining details because you are smart).
Improving your code by using Sieve of Eratosthenes: As many have mentioned, the sieve of Eratosthenes is much better for solving this. In fact, it is super-duper fast. But the one issue often overlooked is how big to make your sieve length to be sure that you captured the prime you are after, without making it outrageously large? The Prime Number Theorem gives an estimate to how big it should be. But you will need an upper bound. Suggest using n * (ln n * ln ln n).
If I understand correctly, you are taking every number less than 1001 and checking if it has a common denominator. This is extremely slow. The complexity is actually increasing exponentially. What you should do is combine this method with a sieve. Take any primes you find with the common denominator method and and multiply them from from 1 to n until you have all their multiple between 1 and 10001. That way you will skip testing the common denominator method on multiples of all the prime numbers you have already found. For example, try this:
ArrayList<Integer> List = new ArrayList<Integer>();
ArrayList<Integer> Primes = new ArrayList<Integer>();
Primes.add(2);
Integer p=2;
Integer n=105000;
Integer i=1;
while(p < n) {
i=1;
while((p*i)<=n){
List.add(p*i);
i++;
}
while (p < n){
p++;
if(List.contains(p)){}
else {Primes.add(p); break;}
}
}
System.out.println(Primes.get(10000));

Divide times in two boxes and find the minimum difference

Started to learn recursion and I am stuck with this simple problem. I believe that there are more optimized ways to do this but first I'm trying to learn the bruteforce approach.
I have bag A and bag B and have n items each one with some time (a float with two decimal places). The idea is to distribute the items by the two bags and obtain the minimum difference in the two bags. The idea is to try all possible outcomes.
I thought only in one bag (lets say bag A) since the other bag will contain all the items that are not in the bag A and therefore the difference will be the absolute value of total times sum - 2 * sum of the items time that are in the bag A.
I'm calling my recursive function like this:
min = total_time;
recursive(0, items_number - 1, 0);
And the code for the function is this:
void recursive(int index, int step, float sum) {
sum += items_time[index];
float difference = fabs(total_time - 2 * sum);
if (min > difference) {
min = difference;
}
if (!(min == 0.00 || step == 1 || sum > middle_time)) {
int i;
for (i = 0; i < items_number; i++) {
if (i != index) {
recursive(i, step - 1, sum);
}
}
}
}
Imagine I have 4 items with the times 1.23, 2.17 , 2.95 , 2.31
I'm getting the result 0.30. I believe that this is the correct result but I'm almost certain that if it is is pure change because If I try with bigger cases the program stops after a while. Probably because the recursion tree gets to bigger.
Can someone point me in some direction?
Okay, after the clarification, let me (hopefully) point you to a direction:
Let's assume that you know what n is, mentioned in n items. In your example, it was 2n is 4, making n = 2. Let's pick another n, let it be 3 this time, and our times shall be:
1.00
2.00
3.00
4.00
5.00
6.00
Now, we can already tell what the answer is; what you had said is all correct, optimally each of the bags will have their n = 3 times summed up to middle_time, which is 21 / 2 = 10.5 in this case. Since integers may never sum up to numbers with decimal points, 10.5 : 10.5 may never be achieved in this example, but 10 : 11 can, and you can have 10 through 6.00 + 3.00 + 1.00 (3 elements), so... yeah, the answer is simply 1.
How would you let a computer calculate it? Well; recall what I said at the beginning:
Let us assume that you know what n is.
In that case a naive programmer would probably simply put all those inside 2 or 3 nested for loops. 2 if he/she knew that the other half will be determined when you pick a half (by simply fixing the very first element in our group, since that element is to be included in one of the groups), like you also know; 3 if he/she didn't know that. Let's make it with 2:
...
float difference;
int i;
for ( i = 1; i < items_number; i++ ) {
sum = items_time[0] + items_time[i];
int j;
for ( j = i + 1; j < items_number; j++ ) {
sum += items_time[j];
difference = fabs( total_time - 2 * sum );
if ( min > difference ) {
min = difference;
}
}
}
...
Let me comment about the code a little for faster understanding: On the first cycle, it will add up the 0th time, the 1st time and then the 2nd time as you may see; then it will do the same check you had made (calculate the difference and compare the it with min). Let us call this the 012 group. The next group that will be checked will be 013, then 014, then 015; then 023, and so on... Each possible combination that will split the 6 into two 3s will be checked.
This operation shouldn't be any tiresome for the computer to issue. Even with this simple approach, the maximum amount of tries will be the amount of combinations of 3 you could have with 6 unique elements divided by 2. In maths, people denote this as C(6, 3), which evaluates to (6 * 5 * 4) / (3 * 2 * 1) = 20; divided by 2, so it's 10.
My guess is that the computer wouldn't make it a problem even if n was 10, making the amount of combinations as high as C(20, 10) / 2 = 92 378. It would, however, be a problem for you to write down 9 nested for loops by hand...
Anyway, the good thing is, you can recursively nest these loops. Here I will end my guidance. Since you apparently are studying for the recursion already, it wouldn't be good for me to offer a solution at this point. I can assure you that it is do-able.
Also the version I have made on my end can do it within a second for up to items_number = 22, without having made any optimizations; simply with brute force. That makes 352 716 combinations, and my machine is just a simple Windows tablet...
Your problem is called the Partition Problem. It is NP-hard and after some point, it will take a very long time to complete: the tree gets exponentially bigger as the number of cases to test grows.
The partition problem is well known and well documented over the internet. There exists some optimized solution
Your approach is not the naive brute-force approach, which would just walk through the list of items and put it into bag A and bag B recursively, chosing the case with the minimum difference, for example:
double recurse(double arr[], int n, double l, double r)
{
double ll, rr;
if (n == 0) return fabs(l - r);
ll = recurse(arr + 1, n - 1, l + *arr, r);
rr = recurse(arr + 1, n - 1, l, r + *arr);
if (ll > rr) return rr;
return ll;
}
(This code is very naive - it doesn't quite early on clearly non-optimal cases and it also wastes time by calculating every case twice with bags A and B swapped. it is brute force, however.)
You maximum recursion depth is the numer of items n, you call the recursive function 2^n - 1 times.
In your code, you can put the same item into a bag over and over:
for (i = 0; i < number_of_pizzas; i++) {
if (i != index) {
recursive(i, step - 1, sum);
}
}
This loop prevents you from treating the current item, but will happily treat items that have been put into the bag in earlier recursions for a second (or third) time. If you want to use that approach, you must keep a state of which item is in which bag.
Also, I don't understand your step. You start with step - 1 and stop recursion when step == 1. That means you are considering n - 2 items. I understand that the other items are in the other bag, but that's a weird condition that won't let you find the solution to, say, {8.0, 2.4, 2.4, 2.8}.

Resources