codility: Euclidean algorithm ( ChocolatesByNumbers, CommonPrimeDivisors)
Chocolates By Numbers
Two positive integers N and M are given. Integer N represents the number of chocolates arranged in a circle, numbered from 0 to N − 1.
You start to eat the chocolates. After eating a chocolate you leave only a wrapper.
You begin with eating chocolate number 0. Then you omit the next M − 1 chocolates or wrappers on the circle, and eat the following one.
More precisely, if you ate chocolate number X, then you will next eat the chocolate with number (X + M) modulo N (remainder of division).
You stop eating when you encounter an empty wrapper.
For example, given integers N = 10 and M = 4. You will eat the following chocolates: 0, 4, 8, 2, 6.
The goal is to count the number of chocolates that you will eat, following the above rules.
Write a function:
int solution(int N, int M);
that, given two positive integers N and M, returns the number of chocolates that you will eat.
For example, given integers N = 10 and M = 4. the function should return 5, as explained above.
Assume that:
- N and M are integers within the range [1..1,000,000,000].
Complexity:
- expected worst-case time complexity is O(log(N+M));
- expected worst-case space complexity is O(1).
不知道怎么证明N/gcd(N,M),从直观上其实比较好理解。。
// you can also use includes, for example: // #include <algorithm> int gcd (int a, int b) { if(a<b) { return gcd(b,a); } if(a%b==0) { return b; } return gcd(b,a%b); } int solution(int N, int M) { // write your code in C++98 return N/gcd(N,M); }
Common Prime Divisors:
A prime is a positive integer X that has exactly two distinct divisors: 1 and X. The first few prime integers are 2, 3, 5, 7, 11 and 13.
A prime D is called a prime divisor of a positive integer P if there exists a positive integer K such that D * K = P. For example, 2 and 5 are prime divisors of 20.
You are given two positive integers N and M. The goal is to check whether the sets of prime divisors of integers N and M are exactly the same.
For example, given:
- N = 15 and M = 75, the prime divisors are the same: {3, 5};
- N = 10 and M = 30, the prime divisors aren't the same: {2, 5} is not equal to {2, 3, 5};
- N = 9 and M = 5, the prime divisors aren't the same: {3} is not equal to {5}.
Write a function:
int solution(vector<int> &A, vector<int> &B);
that, given two non-empty zero-indexed arrays A and B of Z integers, returns the number of positions K for which the prime divisors of A[K] and B[K] are exactly the same.
For example, given:
A[0] = 15 B[0] = 75 A[1] = 10 B[1] = 30 A[2] = 3 B[2] = 5
the function should return 1, because only one pair (15, 75) has the same set of prime divisors.
Assume that:
- Z is an integer within the range [1..6,000];
- each element of arrays A, B is an integer within the range [1..2147483647].
Complexity:
- expected worst-case time complexity is O(Z*log(max(A)+max(B))2);
- expected worst-case space complexity is O(1), beyond input storage (not counting the storage required for input arguments).
这个比较好办,因为如果a和b是由相同的prime divisor组成,那么a/gcd(a,b)必然是gcd(a,b)的一个因子,对b同理。
// you can also use includes, for example: #include <algorithm> int gcd(int a, int b) { if(a<b) { return gcd(b,a); } if(a%b==0) { return b; } return gcd(b,a%b); } bool isCommon(int a, int b) { int gcdValue = gcd(a,b); int gcdA,gcdB; while(a!=1) { gcdA = gcd(a,gcdValue); if(gcdA==1) break; a = a/gcdA; } if(a!=1) { return false; } while(b!=1) { gcdB = gcd(b,gcdValue); if(gcdB==1) break; b = b/gcdB; } return b==1; } int solution(vector<int> &A, vector<int> &B) { // write your code in C++98 int res = 0; for(int i=0;i<A.size();i++) { if(isCommon(A[i],B[i])) { res++; } } return res; }