Few hours ago, a competition was held on CodeForces , this was one the questions of the competition -
Problem C (You dont have to read/solve it to answer the question)
EDIT : Adding the question here as requested, again, one does not necessarily have to read it.
Slastyona and her loyal dog Pushok are playing a meaningless game that
is indeed very interesting.
The game consists of multiple rounds. Its rules are very simple: in
each round, a natural number k is chosen. Then, the one who says (or
barks) it faster than the other wins the round. After that, the
winner's score is multiplied by k2, and the loser's score is
multiplied by k. In the beginning of the game, both Slastyona and
Pushok have scores equal to one.
Unfortunately, Slastyona had lost her notepad where the history of all
n games was recorded. She managed to recall the final results for each
games, though, but all of her memories of them are vague. Help
Slastyona verify their correctness, or, to put it another way, for
each given pair of scores determine whether it was possible for a game
to finish with such result or not.
Input In the first string, the number of games n (1 ≤ n ≤ 350000) is
given.
Each game is represented by a pair of scores a, b (1 ≤ a, b ≤ 10^9) –
the results of Slastyona and Pushok, correspondingly.
Output For each pair of scores, answer "Yes" if it's possible for a
game to finish with given score, and "No" otherwise.
You can output each letter in arbitrary case (upper or lower).
So I solved it, and after the competition was over, me and my friends were discussing the problems when they asked me what was my answer coming for the following test case -
1
1 1
I said it was "Yes" on my IDE (Dev-C++ 5.11), (as it was supposed to be)
But when we ran it on ideone, it came out to be "No" !!
I thought there must be a problem with my code only, so i tried debugging it when i came across this problem,
My Code -
#include<stdio.h>
using namespace std;
long long int iscube(long long int n)
{
long long int lo = 0;
long long int hi = 1000000;
while(lo < hi)
{
long long int mid = (lo+hi)/2;
if(mid*mid*mid < n)
lo = mid+1;
else
hi = mid;
}
return lo;
}
int main()
{
long long int a,b;
int n;
scanf("%d",&n);
while(n--)
{
scanf("%I64d %I64d",&a,&b);
long long int c = a*b;
long long int cb = iscube(c);
//printf("%lld",cb)
if(cb*cb*cb == c)
{
if(a%cb == 0 && b%cb == 0)
printf("Yes\n");
else
printf("No\n");
continue;
}
printf("No\n");
}
}
When i give the input as
1
1 1
in the above code, the answer comes out to be "No"
BUT if I ONLY uncomment the line above the if statement in the while loop in the main() function,
the answer would be "1 Yes"
(these outputs are the outputs i got when i ran the code on ideone, when running on Dev-C++ 5.11 , i got "Yes" and "1 Yes" as expected)
Now while i was thinking that my my answer of codeforces would be evaluated as WA, After the system test, it came out to be Accepted!
Does anyone have any idea on why this issue is arising?
(Also, could someone add the appropriate tags, if any)
Turn up your warnings, you have undefined behavior in your scanf:
warning: length modifier 'I64' results in undefined behavior or no effect with 'd' conversion specifier [-Wformat]
scanf("%I64d %I64d",&a,&b);
If you change it to scanf("%lld %lld",&a,&b); (C++11), then you'll have defined behavior, however since you're using C++, just use a stream instead:
std::cin >> a >> b;
Demo
Related
OK, to start off I am a complete beginner in a computer science class. I could ask my teacher, but I don't have time to do so. So, expect some really dumb errors that I can't see and I am using eclipse.
here's my code:
#include <iostream>
using namespace std;
int something()
{
int big = 1000;//largest number is 1000
int small = 1;//smallest number is 1
//so, best guess is to go in the middle
int c;//my guesses
int inequality;//used to write if statements
for (int a = 0; a <= 10; a++)
{
cout << "Think about a number between 1-1000" << endl;//what console tells you
c = (big - small) / 2;//my guess will be the midpoint of the two numbers
while (big > small)//while the highest number is ALWAYS greater than the lowest number
{
cout << "Is your number less than, equal to, or greater than my guess? 1-less,2-equal,3-greater" << c << endl;
cin >> inequality;//you tell me whether my guess is too high, low, or equal
if (inequality == 1)//if you say it is too low...
{
small = c;//the smallest number is now my last guess
c = c - (big - small) / 2;//so, I'll take the midpoint of the CURRENT biggest and smallest number
}
else if (inequality == 2)//if you say it is equal...
{
cout << "Yay, I guessed your number." << endl;//cool.
}
else if (inequality == 3)//if you say it is too high...
{
big = c;//biggest number is now my guess
c = c + (big - small) / 2;//so, I'll take the midpoint of the CURRENT biggest and smallest number
}
}
}
system("pause");
return 0;//returns something in int main function
}
int main()
{
something();//so I can actually do code.
}
So my problem:
If I enter 1 after the console enters the first guess, I get 499, which is fine. After the second guess (where I enter 1), I get 249, which is also fine. However, the third guess after I enter 1 gets a random 681, so could someone help me?
It would be most appreciated if you did not rewrite the entire code for me, otherwise that is really suspicious when I turn it in. I am struggling because I do not have very good computer science background, so to improve, I need ideas mostly. Lastly, any way to make my code look a LITTLE more professional would be appreciated :)
Also, my for loop may be a bit off, I'm not sure.
When you calculate next number you need to change range
So you have first
small guess big
+---------+----------+
if user says too small, then the answer is above the guess, so in the range
big - guess and that is what you need to cut in half so instead of
c = c - (big - small)/2
guess = (big - guess) / 2 + guess
if user says too big then the answer is between guess and small
guess = (guess - small) / 2 + small
Try removing the c+ and c - terms from your midpoint calculations.
Edit: Also, try swapping the small = c and big = c statements in the two conditionals.
Your comments are mostly incorrect and that was my source of confusion.
Hope you all are having a great day!
I love programming, but these past days I am having sleepless nights, with CodeChef always returning SIGSEGV errors on my Dynamic Programming solutions.
I am solving this question right now. Here's the question -
In Byteland they have a very strange monetary system. Each Bytelandian
gold coin has an integer number written on it. A coin n can be
exchanged in a bank into three coins: n/2, n/3 and n/4. But these
numbers are all rounded down (the banks have to make a profit). You
can also sell Bytelandian coins for American dollars. The exchange
rate is 1:1. But you can not buy Bytelandian coins. You have one gold
coin. What is the maximum amount of American dollars you can get for
it?
Input
The input will contain several test cases (not more than 10). Each
testcase is a single line with a number n, 0 <= n <= 1 000 000 000. It
is the number written on your coin. Output
For each test case output a single line, containing the maximum amount
of American dollars you can make. Example
Input: 12 2
Output: 13 2 You can change 12 into 6, 4 and 3, and then change these
into $6+$4+$3 = $13. If you try changing the coin 2 into 3 smaller
coins, you will get 1, 0 and 0, and later you can get no more than $1
out of them. It is better just to change the 2 coin directly into $2.
Now I know that it's very easy. And I did get stuck initially when I was declaring a big 10^9 integer long array (Over 1GB of memory..whoo!), but coming back to my senses - I decided to do memoization till 10001, and after that simple recursion. But still - I am making a mistake, and it's giving SIGSEGV error.
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
long long n[100001];
long long calc(long long x) {
if (x < 10001) {
if(n[x] != 0) return n[x];
n[x] = max(x, calc(x/2) + calc(x/3) + calc(x/4));
return n[x];
}
else return max(x, calc(x/2) + calc(x/3) + calc(x/4));
}
int main() {
memset(n, 0, sizeof(n));
n[1] = 1;
n[2] = 2;
n[3] = 3;
n[4] = 4;
n[5] = 5;
n[6] = 6;
for (int i = 7; i < 10001; i++)
n[i] = calc(i);
int t = 10;
while (t--) {
long long c;
scanf("%lld", &c);
printf("%lld\n", calc(c));
}
return 0;
}
I have solved some previous questions too - and all of them gave me this error once or twice. I know this error means that I am trying to access memory that hasn't been allocated, but what is wrong in my approach that I always get this error?
The problem is with the corner case n=0.
calc(0) recurses indefinitely because 0<10001 and n[0]=0. You need to add the terminating condition that calc(0)=0.
Takeaways:
Always check your programming competition solutions on corner cases.
Always ensure that your recursion does not result in an infinite loop.
This question already has answers here:
Making a square() function without x*x in C++
(7 answers)
Closed 4 years ago.
I'm a beginner in programming and trying to learn C++ by the book Programming principles and practice using C++. In some parts of the book there are little exercises that you can try to do, one of this exercises is about calculating the square of a number, here is what my book says :
Implement square() without using the multiply operator, that is, do the x * x by repetead addition (start a variable result to 0 and add x to it x times).
I've already found a solution for this program but my first tentative was something like this :
#include <iostream>
int main()
{
int a = 0;
std::cout << "Enter an integer value : ";
std::cin >> a;
while (a < a * a)
{
a += a;
std::cout << a << "\n";
}
}
I know this code is wrong but I can't understand the output of the progam, if I enter 5 the program prints 10 20 30 40 50 until 8000, why the for loop doesn't stop when a is greater than its square ? I'm just curious to undersant why
Using multiplication when trying to avoid multiplication seems broken. What about this:
int r = 0;
for (int n = 0; n < a; ++n) {
r += a;
}
why the for loop doesn't stop when a is greater than its square ?
Because it never is. If you compare the graph of y=x^2 against the graph of y=x, you will see that the only time y=x is above, is when 0 < x < 1. That's never the case for integers1. Now, since we're talking about computers with limited storage here, there is a thing called overflow, which will cause a very large number to become a very small number. However, signed integer overflow is undefined behavior in C++. So once your loop gets to the point where overflow would happen, you cannot rely on the results.
1. Note that your loop is not set to stop just when a is greater than its square, but when it is greater than or equal to its square. So, your loop will actually stop if a is 0 or 1.
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
I have been trying to solve http://www.spoj.com/problems/SCUBADIV/ question at SPOJ. I have come up with a recursive DP solution.
I am using knapsack approach with a 3 dimensional array to store the number of cylinders, required oxygen weight, and nitrogen weight. At each recursive step I'm checking for the amount of oxygen and nitrogen yet to be filled. If it is negative, it's as good as zero.
#include<bits/stdc++.h>
using namespace std;
#define inf 99999999
int n;
vector<int> o;
vector<int> ni;
vector<int> w;
int ow;
int nw;
int knapsack(int n,int ow,int nw); // n - number of cylinders,ow-wt. of oxygen
// nw-wt. of nitogen.
int main(){
int t;
scanf("%d",&t);
while(t--){
int i;
scanf("%d %d",&ow,&nw);
scanf("%d",&n);
o.resize(n);
ni.resize(n);
w.resize(n);
for(i=0;i<n;i++)
scanf("%d%d%d",&o[i],&ni[i],&w[i]); // o[i] storing wt. of oxygen cylinders
int res = knapsack(n,ow,nw); //ni[i] storing wt. of nitrogen cylinders
printf("%d",res);
}
return 0;
}
int knapsack(int n,int ow,int nw){
int dp[n+1][ow+1][nw+1];
memset(dp,inf,sizeof (dp)); //setting value of array to inf to get minimum weight
int i;
for(i=0;i<n;i++)
dp[i][0][0]=0;
if(dp[n][ow][nw]!= inf)
return dp[n][ow][nw];
else if (ow - o[n-1]>=0 && nw - ni[n-1]>=0)
return dp[n][ow][nw]= min(knapsack(n-1,ow,nw),w[n-1]+knapsack(n-1,ow-o[n-1],nw-ni[n-1]));
else if(ow -o[n-1]<0 && nw - ni[n-1] >=0)
return dp[n][ow][nw]=min(knapsack(n-1,0,nw),w[n-1]+knapsack(n-1,0,nw-ni[n-1]));
else if(ow-o[n-1]>=0 && nw-ni[n-1]<0)
return dp[n][ow][nw]=min(knapsack(n-1,ow,0),w[n-1]+knapsack(n-1,ow-o[n-1],0));
else if(ow-o[n-1]<0 && nw-ni[n-1]<0)
return dp[n][ow][nw]= knapsack(n-1,0,0);
}
This code is not giving the desired result (it's giving -1). Is the approach correct ?
There is a problem with this code:
int dp[n+1][ow+1][nw+1];
memset(dp,inf,sizeof (dp));
The memset() function sets a byte pattern, not a value. Since inf is a larger-than-a-byte value, it is essentially doing inf % 256 and initializing all the bytes in dp[][][] to that value. This is further complicated by dp[][][] being of base type int, so 4 bytes set to the same byte value is something unexpected.
In the case of your value for inf, of 99999999, the byte value will be 0xff, and so all the ints in dp[][][] will be set to -1.
I don't know if this is expected, but it looks like it could be a mistake.
Let M(x, O, N) be the minimum weight of cylinders that will provide O liters of oxygen and N liters of nitrogen by choosing from only cylinders 1 to x. Let O(x), N(x), and W(x) be the amount of oxygen and nitrogen available in the x'th cylinder and the cylinder's weight respectively. Then either we choose to use the x'th cylinder or we don't:
M(x, O, N) = min( W(x) + M(x - 1, O - O(x), N - N(x)), M(x - 1, O, N) )
The base case occurs when we have no cylinders at all.
M(0, O, N) = 0 if O <= 0 and N <= 0, infinity otherwise
I won't be reading your unformatted, cryptically written code to figure out whether it implements this correctly. I will say memset can only be used to set bytes to a given value. Your call is not doing what you think. Additionally, your recursive procedure returns junk if execution reaches the end of the if chain.
Work a small example by hand. Run your code either in a debugger or with printfs inserted to show what's going on. Figure out where its actual execution diverges from your hand calculation.
Yes, it is possible to solve this problem with a recursive approach, but this is not how to do it. There are multiple problems with the code, and 'obviously' it will return -1. The question is I shall try to answer is: tell me some of the things wrong with this code.
Variable names like dp obscure the meaning of the code. Give them meaningful names!
Don't resize a vector and read into a pointer. Read values and push them onto the vector.
Print out the data to ensure you read it right.
The memset function fills with bytes, in this case -1. Use a loop to initialise ints.
The first if statement can only ever return 0 or -1 (or inf once you fix the init). As it is the other code will not be executed.
Assigning a value into dp is of no effect, since it is in automatic storage (on the stack).
I don't understand the chain of if statements. Explain them.
There is no else so the function can fall off the end.
Best to rewrite, debug, and if it still doesn't work come back with something we can read.
Input
The input begins with two positive integers n k (n, k<=10^7). The next n lines of input contain one positive integer ti, not greater than 10^9, each.
Output
Write a single integer to output, denoting how many integers ti are divisible by k.
Example
Input:
7 3
1
51
966369
7
9
999996
11
Output:
4
My Code:
#include <iostream>
using namespace std;
int main()
{
long long n,k, i;
cin>>n;
cin>>k;
int count=0;
for(i=0;i<n;i++)
{
int z;
cin>>z;
if(z%k == 0) count++;
}
cout<<count;
return 0;
}
Now this code produces the correct output. However, its not being accepted by CodeChef(http://www.codechef.com/problems/INTEST) for the following reason: Time Limit Exceeded. How can this be further optimized?
As said by caleb the problem is labeled "Enormous Input Test" so it requires you to use some better/faster I/O methods
just replacing cout with printf and cin with scanf will give you an AC but to improve your execution time you need to use some faster IO method for example reading character by character using getchar_unlocked() will give you a better execution time
so you can read the values by using a function like this , for a better execution time.
inline int read(){
char c=getchar_unlocked();
int n=0;
while(!(c>='0' && c<='9'))
c=getchar_unlocked();
while(c>='0' && c<='9'){
n=n*10 + (c-'0');
c=getchar_unlocked();
}
return n;
}
The linked problem contains the following description:
The purpose of this problem is to verify whether the method you are
using to read input data is sufficiently fast to handle problems
branded with the enormous Input/Output warning. You are expected to be
able to process at least 2.5MB of input data per second at runtime.
Considering that, reading values from input a few bytes at a time using iostreams isn't going to cut it. I googled around a bit and found a drop-in replacement for cin and cout described on CodeChef. Some other approaches you could try include using a memory-mapped file and using stdio.
It might also help to look for ways to optimize the calculation. For example, if ti < k, then you know that k is not a factor of ti. Depending on the magnitude of k and the distribution of ti values, that observation alone could save a lot of time.
Remember: the fact that your code is short doesn't mean that it's fast.