Why I am getting TLE on Lightoj 1176 problem? - c

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.

Related

How many matrices have trace equal to givan trace?

I have given a trace 'n' of matrix.And I want to find out that how many matrices(of order 2*2 only) are there whose trace is equals to 'n' and all the matrices must be positive invertible , i.e their determinant must be greator than '0'.
For ex:
trace=3
No.of matrices=2
trace=4
No.of matrices=11
trace=5
No.of matrices=30
I have written a code for this,but it is not efficient because my code giving output successfully for n=1500,after that I'm getting time limit exceeded.
Can anyone help me?
My code is:
#include<stdio.h>
int main()
{
int t,n,nsot,i,j,l;
int arr[2000],k;
unsigned long long sum1=0,sum2=0,sum=0;
scanf("%d",&t);
while(t--)
{
sum1=0;
sum2=0;
//sum=0;
scanf("%d",&n);
nsot=n/2;
for(i=1;i<=nsot;i++)
{
arr[i]=i*(n-i);
//printf("%d ",arr[i]);
sum1=0;
for(k=1;k<arr[i];k++)
{
//printf("%f\n",ceil(arr[i]/k));
sum1=sum1+((arr[i] - 1) / k);
}
if(i==(n-i))
sum=sum1;
else
sum=0;
//printf("%d\n",sum);
//printf("%llu",sum2);
sum2=sum1+sum2;
}
printf("%llu\n",(2*sum2)-sum);
}
}
So I'm guessing you want positive matrix elements and determinant > 0.
The possible values for the trace are [1, n - 1]; [2, n - 2] ..., so n -1 values.
We will check, for each of these (O(n) checks), in how many ways we can fill in the remaining elements of the matrix such that the determinant stays positive.
Let the matrix be:
a1 a3
a4 a2
The determinant is then a1*a2 - a3*a4. For a fixed a1 and a2, iterate a3 from 1 to n - 1. You'll then have to solve:
a1*a2 - x*a4 > 0
a1*a2 > x*a4
x < a1*a2 / a4
So you can find x in O(1) => total complexity O(n^2), which should be very fast.
This seems to be what you're doing, except your innermost loop makes it O(n^3) (you also iterate x):
l=1;
while(k*l<arr[i])
{
sum1++;
l++;
}
Say k = 10 and arr[i] = 103. What will l be at the end? Can you find a relation between 10, 103 and the final value of l? That will be your formula.
Your problem is a specialization of the well known problem of integer partitioning. p(n) is the number of ways of writing n as a sum of positive integers (the order does not matter), and p(n,k) is the number of ways to write n as a sum of k integers. Your problem starts from p(n,2), and adds some extra conditions. There is a wealth of literature on integer partitioning algorithms, you should start from one of them.
However, mind that integer partitioning is NP-complete, so it's natural that it will diverge quickly as n grows.

How does this Codechef Factorial Solution in C work?

I'm trying to understand how this code:
#include<stdio.h>
int main()
{
int j,p,k;
long long int n,i;
scanf("%lld",&n);
for(k=n;k>=1;k--)
{
p=0;
scanf("%lld",&i);
for (j=5;j<=i;j*=5)
{
p=p+i/j;
}
printf("%d\n",p);
}
return 0;
}
solves this Codechef problem: http://www.codechef.com/problems/FCTRL
What I'm having troubles understanding is how this loop works:
for (j=5;j<=i;j*=5)
{
p=p+i/j;
}
Why is the j variable set to 5 and could someone walk me trough this loop if I would give the value of 60 to the i variable?
Thanks so much!
In short the problem is to find the number of zeroes of a factorial of number between 1 to 1000000000.
Now take a pencil and a paper. Start with 1. From 1 to 4 there is no 0. First 0 occurs at 5!. The next is at 10! and then at 15!, 20!, ...... This means that number of zeroes increases at the interval of 5.
Coming to the loop
for (j=5;j<=i;j*=5)
{
p=p+i/j;
}
See the i is stand for N here (see the question). Since number of zeroes increases at the interval of 5, j is initialized to 5 and j will be incremented as a multiple of 5 .
Now the simple rule is that the number of trailing zeros in the decimal representation of N! is simply the multiplicity of the prime factor 5 in N!.
In the statement p=p+i/j;, same rule is followed. The author of the program incremented j by 5 till N/j >= 5 leaving N (i.e i) here as it is.
N = i = 30
p = 30/5 + 30/(5*5) = 6 // 30/25 is 1 and does not satisfying the condition N/j >= 5
This algorithm makes more sense if you understand the method they are using to find the number of trailing zeros of a factorial which is outlined in Trailing zero Factorial and in Factorials and Trailing Zeroes. Basically relies on the insight that you need to account for all the products of 5 and 2 in the factorial expansion to discover how many zeros there will be in the end.
The algorithm to finding the number of trailing zeros in x! boils down to to:
Finding successive powers of 5
Dividing x by the result add the truncated result to the total
Stop when the result of division is less than 1 or in this specific case we know this will happen when the result is greater than x
So if go back to the code we can find the following steps:
step 3
| step 1
V V
for (j=5;j<=i;j*=5)
{
p=p+i/j; // step 2
}
This piece of code:
p=0;
scanf("%lld",&i);
for (j=5;j<=i;j*=5)
{
p=p+i/j;
}
counts the number of factor 5 in all the integers in [1, i] and stores the result in p.
Loop 1: j=5, p+=i/5 counts numbers that are divisible by 5 in the range [1, i]
Loop 2: j=25, p+=i/25 counts numbers that are divisible by 25 in the range [1, i] (notice that such numbers have been already counted once in loop 1)
Loop 3: j=125, p+=i/125 counts numbers that are divisible by 125 in the range [1, i] (notice that such numbers have been already counted twice in loop 1 and 2)
....

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}.

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

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);
}

SYNC13C SPOJ Wrong answer

Link to challenge
Ramesh and Suresh get a box full of five stars on lottery each. Since
both the boxes need not have the same number of chocolates, they
decide to play a game. The winner gets to have both the boxes of
chocolates. They play alternatively and Suresh starts the game. Given
the number of chocolates in both the boxes, let them be c1 and c2, the
player takes either c1 or c2 number of chocolates and divide the
remaining box of chocolates to two boxes (these two boxes need not
have the same number of chocolates). The player who cannot make such a
move loses. Input
First line of input contains a number T(1<=T<=1000), the number of
test cases. Then follows T lines each containing two space separated
integers c1 and c2
(1<=c1<=c2<=10000).
Output For each test case print "Ramesh" or "Suresh" depending on who
is the winner.
Input: 2 3 1 4 5
Output: Ramesh Suresh
Here is my attempt, which is giving me the wrong answer. Give me some more test cases, too.
#include<stdio.h>
int main()
{
int t,c1,c2,max,count,min;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&c1,&c2);
min=c1<c2?c1:c2;
max=c1>c2?c1:c2;
if(max%2!=0 && min%2!=0)
printf("Ramesh\n");
else if(min%2==0 && max%2!=0)
printf("Suresh\n");
else if(max%2==0 && min%2!=0)
printf("Ramesh\n");
else printf("Suresh\n");
}
return 0;
}
The code is much simpler than that. First, let me explain the algorithm.
Let W be an array where,
W[i] = 1 if the user wins by choosing to split the box of i chocolates and 0 if he looses.
Lets construct this array and we will be getting a pattern.
W[1] = 0, since one can't split the box of one chocolate.
For all i>1, we have:
W[i] = 1 if there exists integers a and b such that a+b=i and W[a]=W[b]=0 , 0 otherwise.
The above statement implies that, for a user to win by choosing the i chocolate box, he needs make sure that, his opponent looses no matter what box he chooses further. His opponent loosing implies that W[a]=W[b]=0 and a+b=i.
If we try to fill up this array we get,
W : 1 2 3 4 5 6 7...
val: 0 1 0 1 0 1 0...
This means if one the given integers is even, then suresh is going to win. If both of them are odd, it means ramesh will win.
Hope I am clear.
#include<stdio.h>
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int a,b;
scanf("%d%d",&a,&b);
if(a%2==1 && b%2==1)
printf("Ramesh\n");
else
printf("Suresh\n");
}
return 0;
}

Resources