In the "C++ Without Fear: A Beginner's Guide That Makes You Feel Smart" book, in Chapter (2): Decisions, Decisions, you can see this lin of code as part of the prime number program:
while (i<=sqrt(static_cast<double>(n))
Provided that "i" was initialized to "2", and "n" is the user's input.
Why are we comparing to the "sqrt" of "n" and not to "n" itself?
Thanks.
Because you won't get any factors for non-primes which are > sqrt(n) (you would have already found the other, smaller factor).
It's a really bad test though, it would be much better to write it as:
while (i*i <= n)
Because if a number has factors other than itself and 1, then at least one of those factors will be less than the number's sqrt.
while (i<=sqrt(static_cast<double>(n))
Is equivalent to
while(n >= i*i)
Why the author choose the first solution may depend on other parts of the code.
The code goes like this:
i = 2;
while (i <= sqrt(static_cast<double>(n)) {
if (n % i == 0) is_prime = false;
i++;
}
So the loop is checking if n is divisible by i without remainder. Obviously, only has to check this up to (and including) the square root of n (because if n / p = q then also n / q = p).
Algorithmically it is correct to check possible factors up to the square root of your target.
If N is a number that may or may not be prime, if there are no factors (not including 1) up to sqrt(N) then N must be prime. sqrt(N) itself may well be its only prime factor (eg 9 which is 3*3).
If we are going to test to see if 17 is prime, we know that sqrt(17) is just above 4. 2, 3 and 4 do not divide into 17 so it must be prime as 5 is greater.
This must be the case because 17/5 will be less than 5 and would have to be a factor too, but we know there are no factors less than 5.
Programmatically of course the code is not optimal, as you would not use doubles and square-roots but something like (i*i <= N)
Related
Inputs are two values 1 <= m , n <= 10^12
i don't know why my code is taking soo long for large values . time limit is 1 sec. please suggest me some critical modifications.
#include<iostream>
#include<algorithm>
using namespace std;
int main()
{
unsigned long long m,n,count=0;
cin >> m >> n;
for (long long int i = 1; i <= ((min(m,n))/2)+1; i++) //i divided min(m,n) by 2 to make it efficient.
{
if ((m%i == 0) && (n%i == 0))
{
count++;
}
}
if (((n%m == 0) || (m%n == 0)) && (n!=m))
{
cout << count << endl;
}
printf("%lld",count); //cout<<count;
system("pause");
return 0;
}
Firstly
((min(m, n)) / 2) + 1
Is being calculated every iteration. But it's loop-invariant. In general loop invariant code can be calculated before the loop, and stored. It will add up, but there are obviously much better ways to improve things. I'll describe one below:
you can make this much faster by calculating how many common prime factors there are, and by dividing out any "found" primes as you go. e.g. if only one number is divisible by 5, and the other is not, you can divide that one by 5 and you still get the same answer for common factors. Divide m and n by any "found" numbers as you go through it. (but keep checking whether either is divisible by e.g. 2 and keep dividing before you go on).
e.g. if the two numbers are both divisible by 2, 3 and 5, then the number of ways those three primes can combine is 8 (2^3), treating the presence of each prime as a true/false thing. So each prime that occurs once multiplies the number of combos by 2.
If any of the primes occurs more than once, then it changes the equation slightly. e.g. if the two numbers are divisible by 4, 3, 5:
4 = 2^2, so you could have no "2s", 1 "2" or 2 "2s" in the combined factor, so the total combinations 3 x 2 x 2 = 12. So any prime that occurs "x" times, multiplies the total number of combos by "x+1".
So basically, you don't need to check for every actual factor, you just need to search for how many common prime factors there are, then work out how many combos that adds up to. Luckily you only need to store one value, "total_combos" and multiply it by the "x+1" value for each found number as you go.
And a handy thing is that you can divide out all primes as they're found, and you're guaranteed that the largest remaining prime to be found is no larger than the square root of the smallest remaining number out of m and n.
So to run you through how this would work, start with a copy of m and n, loop up to the sqrt of the min of those two (m and n will be reduced as the loop cycles through).
make a value "total_combos", which starts at 1.
Check for 2's first, find out how many common powers of 2 there are, add one to that number. Divide out ALL the 2's from m and n, even if they're not matched, because reducing down the number cuts the total amount you actually need to search. You count the 2's, add one, then multiply "total_combos" by that. Keep dividing m or n by two as long as either has a factor of 2 remaining.
Then check for 3's, find out how many common powers of 3 there are, add one, the multiply "total_combos" by that. Divide out any and all factors of 3 when you're doing this.
then check for 4's. Since 4 isn't prime and we got rid of all 2's already, there will be zero 4's. Add one to that = 1, then we times "total_combos" by 1, so it stays the same. We didn't need to check whether 4 was prime or not, the divisions we already did ensured it's ignored. Same for any power of 2.
then check for 5's. same deal as 2's and 3's. And so on. All the prime bases get divided out as you go, so whenever a value actually matches you can be sure it's a new prime.
stop the loop when it exceeds sqrt(max(m,n)) (EDITED: min is probably wrong there). But m and n here are the values that have had all the lower primes divided out, so it's much faster.
I hope this approach is helpful.
There is a better way to solve this problem.
All you have to do is take the GCD of two numbers. Now any number won't divide m & n if they are greater than their GCD. So all you to do is that run a loop till the i<=Math.sqrt(GCD(m,n)) and check if the m%i==0 and n%i==0 only. It will save a lot of nanosecs.
my teacher gave me this :
n<=10^6;
an array of n integer :ai..an(ai<=10^9);
find all prime numbers .
he said something about sieve of eratosthenes,and I read about it,also the wheel factorization too,but I still couldn't figure it out how to get the program (fpc) to run in 1s.??
as I know it's impossible,but still want to know your opinion .
and with the wheel factorization ,a 2*3 circle will treat 25 as a prime number,and I wanna ask if there is a way to find out the first number of the wheel treated wrong as a prime number.
example:2*3*5 circle ,how to find the first composite number treated as aprime number??
please help..and sorry for bad english.
A proper Sieve of Eratosthenes should find the primes less than a billion in about a second; it's possible. If you show us your code, we'll be happy to help you find what is wrong.
The smallest composite not marked by a 2,3,5-wheel is 49: the next largest prime not a member of the wheel is 7, and 7 * 7 = 49.
I did it now and it's finding primes up to 1000000 in a few milliseconds, without displaying all those numbers.
Declare an array a of n + 1 bools (if it is zero-based). At the beginning 0th and 1st element are false, all others are true (false is not a prime).
The algorithm looks like that:
i = 2;
while i * i <= n
if a[i] == true
j = i * i;
while j < n
a[j] = false;
j = j + i;
i = i + 1;
In a loop the condition is i * i <= n because you start searching from i * i (smaller primes than that was found already by one of other primes) so square root of i must not be bigger than n. You remove all numbers which are multiplies of primes up to n.
Time complexity is O(n log log n).
If you want to display primes, you display indexes which values in array are true.
Factorization is usefull if you want to find e.g. all semiprimes from 0 to n (products of two prime numbers). Then you find all smallest prime divisors from 0 to n/2 and check for each number if it has prime divisor and if number divided by its prime divisor has zero divisors. If so - it is a semiprime. My program wrote like that was calculating 8 times faster than first finding all primes and then multiplying them and saving result in an array.
An array of integers A[i] (i > 1) is defined in the following way: an element A[k] ( k > 1) is the smallest number greater than A[k-1] such that the sum of its digits is equal to the sum of the digits of the number 4* A[k-1] .
You need to write a program that calculates the N th number in this array based on the given first element A[1] .
INPUT:
In one line of standard input there are two numbers seperated with a single space: A[1] (1 <= A[1] <= 100) and N (1 <= N <= 10000).
OUTPUT:
The standard output should only contain a single integer A[N] , the Nth number of the defined sequence.
Input:
7 4
Output:
79
Explanation:
Elements of the array are as follows: 7, 19, 49, 79... and the 4th element is solution.
I tried solving this by coding a separate function that for a given number A[k] calculates the sum of it's digits and finds the smallest number greater than A[k-1] as it says in the problem, but with no success. The first testing failed because of a memory limit, the second testing failed because of a time limit, and now i don't have any possible idea how to solve this. One friend suggested recursion, but i don't know how to set that.
Anyone who can help me in any way please write, also suggest some ideas about using recursion/DP for solving this problem. Thanks.
This has nothing to do with recursion and almost nothing with dynamic programming. You just need to find viable optimizations to make it fast enough. Just a hint, try to understand this solution:
http://codepad.org/LkTJEILz
Here is a simple solution in python. It only uses iteration, recursion is unnecessary and inefficient even for a quick and dirty solution.
def sumDigits(x):
sum = 0;
while(x>0):
sum += x % 10
x /= 10
return sum
def homework(a0, N):
a = [a0]
while(len(a) < N):
nextNum = a[len(a)-1] + 1
while(sumDigits(nextNum) != sumDigits(4 * a[len(a)-1])):
nextNum += 1
a.append(nextNum)
return a[N-1]
PS. I know we're not really supposed to give homework answers, but it appears the OP is in an intro to C++ class so probably doesn't know python yet, hopefully it just looks like pseudo code. Also the code is missing many simple optimizations which would probably make it too slow for a solution as is.
It is rather recursive.
The kernel of the problem is:
Find the smallest number N greater than K having digitsum(N) = J.
If digitsum(K) == J then test if N = K + 9 satisfies the condition.
If digitsum(K) < J then possibly N differs from K only in the ones digit (if the digitsum can be achieved without exceeding 9).
Otherwise if digitsum(K) <= J the new ones digit is 9 and the problem recurses to "Find the smallest number N' greater than (K/10) having digitsum(N') = J-9, then N = N'*10 + 9".
If digitsum(K) > J then ???
In every case N <= 4 * K
9 -> 18 by the first rule
52 -> 55 by the second rule
99 -> 189 by the third rule, the first rule is used during recursion
25 -> 100 requires the fourth case, which I had originally not seen the need for.
Any more counterexamples?
To find whether N is a prime number we only need to look for all numbers less or equal to sqrt(N). Why is that? I am writing a C code so trying to understand a reason behind it.
N is prime if it is a positive integer which is divisible by exactly two positive integers, 1 and N. Since a number's divisors cannot be larger than that number, this gives rise to a simple primality test:
If an integer N, greater than 1, is not divisible by any integer in the range [2, N-1], then N is prime. Otherwise, N is not prime.
However, it would be nice to modify this test to make it faster. So let us investigate.
Note that the divisors of N occur in pairs. If N is divisible by a number M, then it is also divisible by N/M. For instance, 12 is divisble by 6, and so also by 2. Furthermore, if M >= sqrt(N), then N/M <= sqrt(N).
This means that if no numbers less than or equal to sqrt(N) divide N, no numbers greater than sqrt(N) divide N either (excepting 1 and N themselves), otherwise a contradiction would arise.
So we have a better test:
If an integer N, greater than 1, is not divisible by any integer in the range [2, sqrt(N)], then N is prime. Otherwise, N is not prime.
if you consider the reasoning above, you should see that a number which passes this test also passes the first test, and a number which fails this test also fails the first test. The tests are therefore equivalent.
A composite number (one that is not prime, or 1) has at least 1 pair of factors, and it is guaranteed that one of the numbers from each pair is less than or equal to the square root of the number (which is what you are asking about).
If you square the square root of the number, you get the number itself (sqrt(n) * sqrt(n) = n), so if you made one of the numbers bigger (than sqrt(n)) you would have to make the other one smaller. If you then only check the numbers 2 through sqrt(n) you will have checked all of the possible factors, since each of those factors will be paired with a number that is greater than sqrt(n) (except of course if the number is in fact a square of some other number, like 4, 9, 16, etc...but that doesn't matter since you know they aren't prime; they are easily factored by sqrt(n) itself).
The reason is simple, any number bigger than the sqrt, will cause the other multiplier, to be smaller than the sqrt. In such case, you should have already check it.
Let n=a×b be composite.
Assume a>sqrt(n) and b>sqrt(n).
a×b > sqrt(n)×sqrt(n)
a×b > n
But we know a×b=n, therefore a<sqrt(n) or b<sqrt(n).
Since you only need to know a or b to show n is composite, you only need to check the numbers up to sqrt(n) to find such a number.
Because in the worst case, number n can be expresed as a2.
If the number can be expressed diferently, that men that one of divisors will be less than a = sqrt(n), but the other can be greater.
An algorithm which will take two positive numbers N and K and calculate the biggest possible number we can get by transforming N into another number via removing K digits from N.
For ex, let say we have N=12345 and K=3 so the biggest possible number we can get by removing 3 digits from N is 45 (other transformations would be 12, 15, 35 but 45 is the biggest). Also you cannot change the order of the digits in N (so 54 is NOT a solution). Another example would be N=66621542 and K=3 so the solution will be 66654.
I know this is a dynamic programming related problem and I can't get any idea about solving it. I need to solve this for 2 days, so any help is appreciated. If you don't want to solve this for me you don't have to but please point me to the trick or at least some materials where i can read up more about some similar issues.
Thank you in advance.
This can be solved in O(L) where L = number of digits. Why use complicated DP formulas when we can use a stack to do this:
For: 66621542
Add a digit on the stack while there are less than or equal to L - K digits on the stack:
66621. Now, remove digits from the stack while they are less than the currently read digit and put the current digit on the stack:
read 5: 5 > 2, pop 1 off the stack. 5 > 2, pop 2 also. put 5: 6665
read 4: stack isnt full, put 4: 66654
read 2: 2 < 4, do nothing.
You need one more condition: be sure not to pop off more items from the stack than there are digits left in your number, otherwise your solution will be incomplete!
Another example: 12345
L = 5, K = 3
put L - K = 2 digits on the stack: 12
read 3, 3 > 2, pop 2, 3 > 1, pop 1, put 3. stack: 3
read 4, 4 > 3, pop 3, put 4: 4
read 5: 5 > 4, but we can't pop 4, otherwise we won't have enough digits left. so push 5: 45.
Well, to solve any dynamic programming problem, you need to break it down into recurring subsolutions.
Say we define your problem as A(n, k), which returns the largest number possible by removing k digits from n.
We can define a simple recursive algorithm from this.
Using your example, A(12345, 3) = max { A(2345, 2), A(1345, 2), A(1245, 2), A(1234, 2) }
More generally, A(n, k) = max { A(n with 1 digit removed, k - 1) }
And you base case is A(n, 0) = n.
Using this approach, you can create a table that caches the values of n and k.
int A(int n, int k)
{
typedef std::pair<int, int> input;
static std::map<input, int> cache;
if (k == 0) return n;
input i(n, k);
if (cache.find(i) != cache.end())
return cache[i];
cache[i] = /* ... as above ... */
return cache[i];
}
Now, that's the straight forward solution, but there is a better solution that works with a very small one-dimensional cache. Consider rephrasing the question like this: "Given a string n and integer k, find the lexicographically greatest subsequence in n of length k". This is essentially what your problem is, and the solution is much more simple.
We can now define a different function B(i, j), which gives the largest lexicographical sequence of length (i - j), using only the first i digits of n (in other words, having removed j digits from the first i digits of n).
Using your example again, we would have:
B(1, 0) = 1
B(2, 0) = 12
B(3, 0) = 123
B(3, 1) = 23
B(3, 2) = 3
etc.
With a little bit of thinking, we can find the recurrence relation:
B(i, j) = max( 10B(i-1, j) + ni , B(i-1, j-1) )
or, if j = i then B(i, j) = B(i-1, j-1)
and B(0, 0) = 0
And you can code that up in a very similar way to the above.
The trick to solving a dynamic programming problem is usually to figuring out what the structure of a solution looks like, and more specifically if it exhibits optimal substructure.
In this case, it seems to me that the optimal solution with N=12345 and K=3 would have an optimal solution to N=12345 and K=2 as part of the solution. If you can convince yourself that this holds, then you should be able to express a solution to the problem recursively. Then either implement this with memoisation or bottom-up.
The two most important elements of any dynamic programming solution are:
Defining the right subproblems
Defining a recurrence relation between the answer to a sub-problem and the answer to smaller sub-problems
Finding base cases, the smallest sub-problems whose answer does not depend on any other answers
Figuring out the scan order in which you must solve the sub-problems (so that you never use the recurrence relation based on uninitialized data)
You'll know that you have the right subproblems defined when
The problem you need the answer to is one of them
The base cases really are trivial
The recurrence is easy to evaluate
The scan order is straightforward
In your case, it is straightforward to specify the subproblems. Since this is probably homework, I will just give you the hint that you might wish that N had fewer digits to start off with.
Here's what i think:
Consider the first k + 1 digits from the left. Look for the biggest one, find it and remove the numbers to the left. If there exists two of the same biggest number, find the leftmost one and remove the numbers to the left of that. store the number of removed digits ( name it j ).
Do the same thing with the new number as N and k+1-j as K. Do this until k+1 -j equals to 1 (hopefully, it will, if i'm not mistaken).
The number you end up with will be the number you're looking for.