Finding numbers with given GCD values - c++

I was looking over the Eucledian algorithm for finding GCD of numbers. Now, it can be used to find GCD of two given numbers. However, if I am given GCD of a single number with multiple other numbers, for example, GCD of the first number with 3 other numbers (including itself), that is,
Given is: GCD of a with a, GCD of a with b, GCD of a with c, GCD of a with d.
and same goes for the other numbers, i.e. GCD of b with a, b with b, .....
Then, how can I find the individual numbers? I know that GCD(a,a) = a itself but the problem here is, that the individual GCD given are in a random order, and therefore, I don't know which input number is the GCD of which two numbers. In that case, how do I find the individual numbers?
Here is my GCD code:
int gcd(int a,int b)
{
if(b==0)
{
return a;
}
return gcd(b,a%b);
}
Example: Let's say the input given is,
3 1 3 1 4 2 2 3 6
3 //(total numbers we have to find in original array)
Then output should be, 3 4 6. Because if you calculate GCD pairwise (total 9 pairs and hence 9 numbers as input) of each of these numbers, then we get the output as above.
Explanation: 3 -> GCD of (3,3)
1 -> GCD of (3,4)
3 -> GCD of (3,6)
1 -> GCD of (4,3)
4 -> GCD of (4,4)
2 -> GCD of (4,6)
6 -> GCD of (6,6)
3 -> GCD of (6,3)
2 -> GCD of (6,4)
Therefore, I have to find the numbers whose GCD is given as input. Hence, (3,4,6) are those numbers.

I think you can do this by the following process:
Find and remove largest number, this is one of the original numbers
Compute the gcd of the number just found in step 1, with all numbers previously found in step 1.
Remove each of these computed gcds from the input array of gcds (Strictly speaking remove 2 copies of each gcd)
Repeat until all numbers are found
The point is that this only goes wrong if the largest number x found in step 1 is not one of the original numbers. However, this can only happen if x is a gcd of two other numbers. These other numbers must be at least as large as x, but all such gcds have been removed in step 3. Therefore x is always one of the original numbers.

If the second line of the input is 1, then the first line of the input will have only one number, and due to your observation that gcd(a, a) = a, the value of a will be whatever value is on the first line of input.
If the value on the second line of input is greater than 1, then the problem can be reduced using the following observation. Given positive integers a and b, we know that gcd(a, b) <= a = gcd(a, a) and gcd(a, b) <= b = gcd(b, b) will always hold. Therefore, we can conclude that the largest two numbers on the first line of input must both be part of the basic set of numbers. The largest two numbers may be equal, but in your example, they are 4 and 6, and they are not equal.
If there are more than two numbers to find, let's call the largest two a and b. Since we now know the value of a and b, we can compute gcd(a, b) and remove two occurrences of that value from consideration as one of the input numbers. We remove two occurrences because gcd(a, b) = gcd(b, a) are both in the list of input numbers. Then using similar logic, we conclude that the largest number remaining after a, b, gcd(a, b), and gcd(b, a) are removed must be one of the input numbers.
Wash, rinse, repeat.

This is actually pretty easy:
count how many times each distinct number appears in the array
if that count is odd, then that is one of the numbers in your set
if that count is even, that is not one of the numbers in your set.
done.
This works because when x != y, gcd(x,y) = gcd(y,x) and that number will be in the array twice. Only values that come from gcd(x,x) will be in the array once, leading to an odd number of that specific value.

As we see here, that for each number with other number a GCD is calculated and added to the existing list, like this in the end we would be having n*n total numberer for original n numbers. So the same approach can be reverse used to find original numbers
Sort the list in descending order.
Collect top n^(0.5) numbers, that would be our answer.
For your example
3 1 3 1 4 2 2 3 6
Sorted = 6 4 3 3 3 2 2 1 1
value of n = 9
value of n^(0.5) = 3
choose top 3 numbers 6,4 and 3. Thats our answer

Related

Printing sum of non abundant numbers in haskell

This is a Project Euler Problem 23: Non-abundant Sums.
A perfect number is a number for which the sum of its proper divisors is exactly equal to the number. For example, the sum of the proper divisors of 28 would be 1 + 2 + 4 + 7 + 14 = 28, which means that 28 is a perfect number.
A number n is called deficient if the sum of its proper divisors is less than n and it is called abundant if this sum exceeds n.
As 12 is the smallest abundant number, 1 + 2 + 3 + 4 + 6 = 16, the smallest number that can be written as the sum of two abundant numbers is 24. By mathematical analysis, it can be shown that all integers greater than 28123 can be written as the sum of two abundant numbers. However, this upper limit cannot be reduced any further by analysis even though it is known that the greatest number that cannot be expressed as the sum of two abundant numbers is less than this limit.
Find the sum of all the positive integers which cannot be written as the sum of two abundant numbers.
Here the sumOfPD function returns the sum of proper divisors.
I wrote the following code which doesn't work.
sumOfPD :: Integral a => a -> a
sumOfPD x = sum([y | y <- [1..x], rem x y == 0]) - x
main = do
print (sum ([x + y | x <- [1..], y <- [1..], x + y < 28124, sumOfPD x <= x, sumOfPD y <= y]))
I'm new to Haskell. Please help me resolve error.
You have two problems. One is largely mathematical and one is largely about Haskell semantics. Both stem from a lack of care and clarity of thought; you should think more carefully and slowly about how to write a program which does less work to get to the answer. I'm not going to write down any solution or correct version (indeed project Euler discourages sharing solutions) as that won't help you and it won't help anyone who comes across this by google.
In your sum in main you're counting some numbers multiple times. For example $1+2+4+5+10=21>20$ so 20 is abundant. Your list includes $32=12+20=20+12$ at least twice. Note [32,32] /= [32]. Also note that this isn't just an issue with counting $x+y$ and $y+x$, there might be some numbers which are the sum of two ambiguous in two (non-trivially) different ways.
Due to the nature of list comprehensions in Haskell, in main, x will only ever take a value of 1 as the values considered are (x,y)=(1,1),(1,2),(1,3),(1,4),... and then each of those values is tested. There is a point after which all values are rejected as x+y>=28124 but you never move on to the next x value. Indeed all values are rejected as 1 is not abundant. Try changing [1..] to [1..n] where n is something you should decide on. Alternatively, change it to a list of abundant numbers up to some limit. Cf takeWhile and filter

Total number of common factors for two numbers LARGE VALUES upto 10^12

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.

how to find the minimum number of primatics that sum to a given number

Given a number N (<=10000), find the minimum number of primatic numbers which sum up to N.
A primatic number refers to a number which is either a prime number or can be expressed as power of prime number to itself i.e. prime^prime e.g. 4, 27, etc.
I tried to find all the primatic numbers using seive and then stored them in a vector (code below) but now I am can't see how to find the minimum of primatic numbers that sum to a given number.
Here's my sieve:
#include<algorithm>
#include<vector>
#define MAX 10000
typedef long long int ll;
ll modpow(ll a, ll n, ll temp) {
ll res=1, y=a;
while (n>0) {
if (n&1)
res=(res*y)%temp;
y=(y*y)%temp;
n/=2;
}
return res%temp;
}
int isprimeat[MAX+20];
std::vector<int> primeat;
//Finding all prime numbers till 10000
void seive()
{
ll i,j;
isprimeat[0]=1;
isprimeat[1]=1;
for (i=2; i<=MAX; i++) {
if (isprimeat[i]==0) {
for (j=i*i; j<=MAX; j+=i) {
isprimeat[j]=1;
}
}
}
for (i=2; i<=MAX; i++) {
if (isprimeat[i]==0) {
primeat.push_back(i);
}
}
isprimeat[4]=isprimeat[27]=isprimeat[3125]=0;
primeat.push_back(4);
primeat.push_back(27);
primeat.push_back(3125);
}
int main()
{
seive();
std::sort(primeat.begin(), primeat.end());
return 0;
}
One method could be to store all primatics less than or equal to N in a sorted list - call this list L - and recursively search for the shortest sequence. The easiest approach is "greedy": pick the largest spans / numbers as early as possible.
for N = 14 you'd have L = {2,3,4,5,7,8,9,11,13}, so you'd want to make an algorithm / process that tries these sequences:
13 is too small
13 + 13 -> 13 + 2 will be too large
11 is too small
11 + 11 -> 11 + 4 will be too large
11 + 3 is a match.
You can continue the process by making the search function recurse each time it needs another primatic in the sum, which you would aim to have occur a minimum number of times. To do so you can pick the largest -> smallest primatic in each position (the 1st, 2nd etc primatic in the sum), and include another number in the sum only if the primatics in the sum so far are small enough that an additional primatic won't go over N.
I'd have to make a working example to find a small enough N that doesn't result in just 2 numbers in the sum. Note that because you can express any natural number as the sum of at most 4 squares of natural numbers, and you have a more dense set L than the set of squares, so I'd think it rare you'd have a result of 3 or more for any N you'd want to compute by hand.
Dynamic Programming approach
I have to clarify that 'greedy' is not the same as 'dynamic programming', it can give sub-optimal results. This does have a DP solution though. Again, i won't write the final process in code but explain it as a point of reference to make a working DP solution from.
To do this we need to build up solutions from the bottom up. What you need is a structure that can store known solutions for all numbers up to some N, this list can be incrementally added to for larger N in an optimal way.
Consider that for any N, if it's primatic then the number of terms for N is just 1. This applies for N=2-5,7-9,11,13,16,17,19. The number of terms for all other N must be at least two, which means either it's a sum of two primatics or a sum of a primatic and some other N.
The first few examples that aren't trivial:
6 - can be either 2+4 or 3+3, all the terms here are themselves primatic so the minimum number of terms for 6 is 2.
10 - can be either 2+8, 3+7, 4+6 or 5+5. However 6 is not primatic, and taking that solution out leaves a minimum of 2 terms.
12 - can be either 2+10, 3+9, 4+8, 5+7 or 6+6. Of these 6+6 and 2+10 contain non-primatics while the others do not, so again 2 terms is the minimum.
14 - ditto, there exist two-primatic solutions: 3+11, 5+9, 7+7.
The structure for storing all of these solutions needs to be able to iterate across solutions of equal rank / number of terms. You already have a list of primatics, this is also the list of solutions that need only one term.
Sol[term_length] = list(numbers). You will also need a function / cache to look up some N's shortest-term-length, eg S(N) = term_length iif N in Sol[term_length]
Sol[1] = {2,3,4,5 ...} and Sol[2] = {6,10,12,14 ...} and so on for Sol[3] and onwards.
Any solution can be found using one term from Sol[1] that is primatic. Any solution requiring two primatics will be found in Sol[2]. Any solution requiring 3 will be in Sol[3] etc.
What you need to recognize here is that a number S(N) = 3 can be expressed Sol[1][a] + Sol[1][b] + Sol[1][c] for some a,b,c primatics, but it can also be expressed as Sol[1][a] + Sol[2][d], since all Sol[2] must be expressible as Sol[1][x] + Sol[1][y].
This algorithm will in effect search Sol[1] for a given N, then look in Sol[1] + Sol[K] with increasing K, but to do this you will need S and Sol structures roughly in the form shown here (or able to be accessed / queried in a similar manner).
Working Example
Using the above as a guideline I've put this together quickly, it even shows which multi-term sum it uses.
https://ideone.com/7mYXde
I can explain the code in-depth if you want but the real DP section is around lines 40-64. The recursion depth (also number of additional terms in the sum) is k, a simple dual-iterator while loop checks if a sum is possible using the kth known solutions and primatics, if it is then we're done and if not then check k+1 solutions, if any. Sol and S work as described.
The only confusing part might be the use of reverse iterators, it's just to make != end() checking consistent for the while condition (end is not a valid iterator position but begin is, so != begin would be written differently).
Edit - FYI, the first number that takes at least 3 terms is 959 - had to run my algorithm to 1000 numbers to find it. It's summed from 6 + 953 (primatic), no matter how you split 6 it's still 3 terms.

Digit manipulation number conversion

I have 4 digit number from 0000 to 1440. I want to generate an equivalent four digit number. That means I can reverse the number from the equivalent number. Basic requirement is the equivalent number must be completely different from the original one. Is there a good equation to do this?
For example, each digit can be replaced by 10 - digit. Thus, 1440 becomes 9660, and 1254 becomes 9756.
Thanks.
You can use a Linear Congruential Generator with a period of 10000. This is a pseudo-random number generator that cycles through each number in the range of 0-9999 once and only once. To generate your number, just take the original number and calculate the next number in the LCG sequence.
An LCG generates random numbers using the following formula:
Xn+1 = ((Xn * a) + c) mod m
To generate 4-digit numbers m should be 10000 (range of 0-9999).
To guarantee no repeats (a "full period") you have to select values for a and c using the following criteria:
c and m are relatively prime
a - 1 is divisible by all prime factors of m
a - 1 is a multiple of 4 if m is a multiple of 4.
The prime factors of 10000 are 2 and 5, and it's also divisible by 4, so any multiple of 20 + 1 will work as a suitable value of a. For c just choose a reasonably large prime number.
e.g: m = 10000, a = 4781, c = 7621
To go the other way, you need to make the function reversible. See this answer for an explanation of the math behind that.
Here's a simple implementation:
#define M (10000)
#define A (4781)
#define C (7621)
int extendedEuclidY(int a, int b);
int extendedEuclidX(int a, int b)
{
return (b==0) ? 1 : extendedEuclidY(b, a-b*(a/b));
}
int extendedEuclidY(int a, int b)
{
return (b==0) ? 0 : extendedEuclidX(b, a-b*(a/b)) - (a/b) * extendedEuclidY(b, a-b*(a/b));
}
int forward(int x)
{
return ((x*A)+C)%M;
}
int backward(int x)
{
return ((extendedEuclidX(A, M)*(x-C)%M)+M)%M;
}
int main()
{
int x;
for(x=0; x<1440; x++)
{
printf("%d <-> %d\n", backward(forward(x)), forward(x));
}
return 0;
}
I've adapted the extendedEuclid functions from the linked answer.
forward(x) finds your equivalent number, backward(x) gets the original back.
This is, perhaps, more of a comment.
I think your question is rather vague, because you don't define "completely different". Typical "easy" ways are something like:
Reverse the number.
Substitute the digits for other digits (an easy way is to increment each digit by 1).
Substitute pairs of digits for other pairs.
And, you can of course combine these.
In your case, you are starting with a range of 1,441 and mapping to a much larger range (10,000). This actually gives you are larger range of possible mappings.
However, the key point is "how different is different"? You should modify your question to explain that point.

graphs divisibility

Given a simple undirected graph containing N vertices numbered 1 to N, each vertex containing a digit from {1,2,..7}. Starting at the vertex 1 with an empty string S, we travel through some vertices (with no limitations) to the vertex N. For every vertex on the way, we add the respective digit to the right of the string S. At last we get S as a decimal integer. You are requested to find such a way satisfying S is divisible by all of its digits, and the sum of digits of S must be as small as possible.
Input
There are several test cases (fifteen at most), each formed as follows:
The first line contains a positive integer N (N ≤ 100).
The second line contains N digits (separated by spaces), the i-th digit is the value of the i-th vertex.
N last lines, each contains N values of {0, 1} (separated by spaces), the j-th value of the i-th line is equal to 1 if there is an edge connecting two vertices (i, j), otherwise 0.
The input is ended with N = 0.
Output
For each test case, output on a line the minimum sum of digits found, or -1 if there's no solution.
example
Input:
4
1 2 1 4
0 1 1 1
1 0 0 1
1 0 0 1
1 1 1 0
Output:
7
please guide me
there can be self loops and cycles such that node 1 and node N can be visted any number of times
If given graph is transformed to some other graph, where cycles are not allowed, this problem can be solved with Dijkstra's algorithm.
To do this, let's start with string divisibility by 7. Look at this sequence: 1, 10, 100, ... (mod 7). Since 7 is a prime number, 107-1 = 1 (mod 7) because of Fermat's little theorem. Which means 1, 10, 100, ... (mod 7) sequence is periodic and period is 6. This will be used to transform the graph and also this allows to recursively compute Sn (mod 7) using Sn-1 (mod 7): Sn = Sn-1 + 10n%6 * n_th_digit (mod 7).
It's necessary to start shortest path search from node N because this path may be ended at one of the several nodes of the transformed graph. Also this allows to determine quickly (using first 2 nodes of the path), if it is allowed to visit node "5", node"4", and other "even" nodes.
Algorithm's open set (the priority queue) should contain the priority itself (sum of digits) as long as 3 additional bits and 3 remainders: is "4" allowed, is "3" visited, is "7" visited, S % 3, S % 7, and S.length % 6.
Graph should be transformed as follows. Each vertex is expanded to 3 vertexes, one is allowed only for S%3==0, others - for S%3==1 and S%3==2. Then each vertex is expanded to 7 (for S%7), and then each vertex is expanded to 6 (for S.length % 6). It is possible to fit all these expansions to the original graph: just add a 3D array (size 3*7*6) of back-pointers to each node. While searching for the shortest path, the non-empty back-pointers determine algorithm's closed set (they disallow cycles). When shortest path is found, back-pointers allow to reconstruct the sequence of nodes in this path. And the moment when shortest path is found is determined by visiting node 1 with (node_3_not_visited || S%3==0) && (node_7_not_visited || S%7==0).
First mathematically find the LCM of the numbers given in the set.
lemme paraphrase the scenario .... given a set of numbers... find the LCM then traverse the vetices in such a way that the their path makes the number .Since its LCM it is number whose sum is mininum
For set {0,1,2,3,4} LCM is 12 so travers from 1 to 2
for set {0,1,2,3,4,5,6,7} LCM is 420..(I think i am right)
Use the A* search algorithm, where the "cost" is the sum of the digits, and divisibility determines which edges you can traverse.