@admin I have logged in with my account at CodeChef then why i am seeing other user name in CodeChef Discuss?

@admin I have logged in with my account at CodeChef then why i am seeing other user name in CodeChef Discuss?
Author:Priyanshu Jain
MEDIUM
DP, Math etc.
Author's solution can be found here.
I am working on a problem and continuously getting TLE. I want to know if there's another way to sort a vector.
Currently I am using
sort(v.begin(),v.end());
Remember I want to avoid the TLE so please suggest me a better method to sort a vector or an array.
EDIT: The goal of the problem is to sort a string in alphabetical order. I am currently using a vector of <char>.
Is there any trick to sort the integers in just a line?
Author:Sunny Aggarwal
Tester:Sergey Kulik
Editorialist:Sunny Aggarwal
Medium
Trees, Segment Trees, Implementation, Queries Handling, Data Structures.
Given a complete binary tree $T$ consisting of $N$ nodes numbered from $1$ to $N$. For a node $v$, its left child is $2 \times v$ if it exists and its right child is $2 \times v + 1$ if it exists. You are asked to process some type of queries on tree $T$ as mentioned below.
Please note that when we say node at distance $D$ from node $X$, you have to consider all the nodes in the tree, not just the ones in the subtree of $X$.
2 X Y Count the number of distinct colors on the unique simple path from node $X$ to node $Y$.
3 X Count the number of distinct colors in the subtree rooted at node $X$.
Subtask 1:
This subtask is easy and scoring.
Create an adjacency list for the given tree and process the queries on the tree using any traversal algorithm like depth first search and breadth first search.
How to process queries of type 1 ?
Start from the given node $U$ and color all the nodes that at most distance of $K$ units from the given node $U$ as shown below.
const int maxn = 1111; vector<int> adj[ maxn ]; int col[ maxn ], n; void query1(int u, int k, int par = 0, int path_len = 0) { // If distance > k units return if( path_len > k ) { return; } // color current node col[u] = path_len; for(auto it: adj[u]) { if( it != par ) { query1(it, k, u, path_len + 1); } } }
Time Complexity: $O(N)$
How to handle queries to type 2 ?
We can simply run a traversal algorithm from one end of the given path to other end and can also maintain a list of colors on the path.
bool ok = false; vector<int> color_list; void query2(int u, int par=0) { if( u == v ) { // if current node is other end // of the path given in the query ok = true; } for( auto it: adj[u] ) { if( it != par && !ok ) { query2(it, u); } } if( ok ) { color_list.push_back(col[u]); } }
Finding distinct colors in the given list is a trivial problem.
Time Complexity: $O(N)$
How to handle queries to type 2 efficiently?
We know that the given tree is complete binary tree and its height is atmost $log_2{N}$. This helps to claim that the distance between any pair of nodes $(U, V)$ in the tree is atmost $2 \times \log_2{N}$.
vector<int> color_list; void query2(int u, int v) { while( u != v ) { if(u < v) { color_list.push_back(col[v]); v /= 2; } else { color_list.push_back(col[u]); u /= 2; } } color_list.push_back(col[u]); }
Time Complexity: $O(log(N))$
How to handle queries of type 3?
Suppose we need to find the number of distinct colors in the subtree rooted at node $u$ which can be easily handled using the given procedure.
vector<int> color_list; void query3(int u, int par=u/2 ) { color_list.push_back( col[u] ); for(auto it: adj[u]) { if( it != par ) { query3(it, u); } } }
Note that the use of par=u/2 is neccessary otherwise it will explore the full tree $T$.
Subtask 2:
It should be noted that the procedure we used to handle queries of type 1 & 3 in the subtask 1 will surely time out for the subtask 2.
How to handle query 1 in this case ?
Let us try to update only a subtree rooted at a node $U$ upto maximum distance of $K$ units. Note that
Note that as the given tree is a complete binary tree, its height will be atmost $\log_2{N}$ and at each level we have a continuous segment from $L$ to $R$ to update with a single value and therefore, a segment tree along with lazy propagation can be used to perform updates in $\log_2{N}$ time.
It should also be noted that in this problem query type $1$ is not limited to subtree only so we also need to apply the above procedure for each ancestor of node $U$ which adds another $\log_2{N}$ factor to our update complexity.
To query efficiently, it is suggested to maintain a bitmask of $2 \times \log_2{N}$ bits (because this is maximum possible distance between any pair of nodes in the tree and hence the maximum color value) in each node of the segment tree such that operations like setting and unsetting a bit on a range can be performed efficiently.
You can learn about segment tree with lazy progagation here. Also try solving this problem.
How to handle queries to type 2?
Efficient method explained to handle queries of type $2$ in first subtask is good enough.
How to handle queries to type 3?
The idea is almost similiar to what we have just explained while updating a subtree but in this case we are asked to query the number of distinct elements in the subtree which is equivalent of taking bitwise OR of all the elements in the subtree and then finding number of set bits in the resultant value. Note that bitwise OR for all the elements can be found by taking bitwise OR for all the segments in the subtree rooted at given node $U$.
Please check the setter's solution for implementation details. Feel free to ask if anything is not clear.
$O((\log_2{N})^3 \times Q)$
Setter's solution can be found here
Tester's solution can be found here
Question : Utkarsh in Gardens
include<bits stdc++.h=""> using namespace std;
int main(){
int v,n;
cin>>v;
bitset<2005>c[2005];
for(int i=0; i<v; i++){
for(int j=0; j<v; j++){
cin>>n;
c[i][j] = n;
}
}
long long int ans=0;
for(int i=0; i<v; i++){
for(int j=i+1; j<v; j++){
n = (c[i]&c[j]).count();
ans += (n*(n-1))/2;
}
}
cout<<ans/2;
return 0;
}
Someone please explain the solution I will be very grateful. Thanks in advance.
How was your test experience and your performance?
My center was at IIT Patna and the test experience was just fine after the 1 hour delay. Much better than last year.
Solved the first one by a simple dfs. No idea why it was included in INOI. For the second one I did a brute force specific to the first two test cases. This brought my total score to 150
Author:Misha Chorniy
Tester:Tuan Anh Tran Dang
Translators:Sergey Kulik (Russian), Team VNOI (Vietnamese) and Hu Zecong (Mandarin)
Editorialist:Tuan Anh Tran Dang
HARD
NONE
Check whether 4 triangles can be joined to create one single triangle.
I guess some of you might expected some nice and short solution for this problem but unfortunately I don’t know one. This problem is just about considering all possible cases and implement them correctly. I underestimated the difficulty of this problem and missed quite a few cases before discussed with the problem setter.
Let’s first consider a simple version of the problem with 2 or 3 triangles.
The only way to join two triangles is to pick the common side and checking whether the two joined angles can make 180 degree (see picture).
With 3 triangles we can first create a triangle from 2 of them and them try to combine the newly created triangle with the remaining. However this is not cover all possibilities (please take a look at the below picture).
This combination is not so hard to test. You just need to find 3 pairs of common sides and make sure the 3 joined angles can make 360 degree.
With the mentioned two sub-problem solved we can clear a major scenarios of this problem in which there is 2 or 3 triangle out of the 4 combined to form a single triangle. We have the following way of combining them:
Note that we should consider all possible permutations of 4 triangles for each cases.
Now we come to the interesting in which we’ll cover the other corner case. I will use picture to express the combination and briefly describe how to detect them.
Assume that we got a configuration {t1, t2, t3, t4} which is 4 triangles in some specific order and orientation. Note that there is 6 possible orientation of a triangles which is corresponding to 3! way of arranging there sides. Let ti.a, ti.b, ti.c are the sides of the triangle ti and ti.A, ti.B, ti.C are the internal angle of its where ti.A is opposite ti.a and ti.B is opposite ti.b and so on.
t1.c = t2.c t3.b = t3.b t4.a = t4.a
t1.B + t2.A + t3.C = 180 t1.A + t2.B + t4.C = 180 t3.A + t2.C + t4.B = 180
t1.c + t2.c = t4.c t3.b + t2.b = t1.b t4.a + t2.a = t3.a
t1.A + t2.A = 180 t3.C + t2.C = 180 t4.B + t2.B = 180
t1.b = t2.b + t3.b t2.c = t3.c t3.a = t4.a
t1.C + t2.C = 180 t2.A + t3.B + t4.C = 180 t1.A + t4.A = 180
I have implemented a solution but unfortunately it isn’t optimized enough to pass the time limit (even though it’s correct). You can still refer to my TLE solution in tester’s solution. The room to optimize is on the backstracking process of case 3, 4, 5. You should have different method for each case and stop as soon as you can see some condition is invalid. You should take a look at the problem setter’s code too.
Why there is no schedule of JAN17 posted till now?
Author:Praveen Dhinwa
Tester:Istvan Nagy
Editorialist:Misha Chorniy
Cakewalk
None
There are $C$ cats and $D$ dogs, and $L$ legs touching the ground. Some of the cats can ride on dogs, but every dog can't have more than 2 cats on his back. Can this be true?
Let's make some obvious observations:
If we have $X$ cats and $Y$ dogs staying on the ground then, the number of legs in the barn equal $4 * (X+Y)$. Therefore if $L$ not divisible by 4, the answer is "no".
Constraints are chosen in such way that solutions with complexity $O(D+C)$ per test case can pass.
Iterate over possible numbers of the cats on Chef's dogs back $G$($G$ must be in the range between $0$ and $2*D$ due to the condition of the dog and 2 cats on his back, and not more than the total number of cats). Hence in the barn $4*(C-G+D)$ legs on the ground, if $4*(C-G+D) = L$ for some $G$, then the answer is "yes", and "no" otherwise.
There is possible to solve problem with $O(1)$ solution per test case. Let $G$ number of the cats on the backs of the dogs, $0 ≤ G ≤ min(C,2*D)$
$4*(C-G)+4*D = L $, there are $C-G$ cats on the ground, therefore total number of legs = $4*(C-G)$+$4*D$
$C-G+D = L/4 $, divide both parts of the equation by $4$
$C+D-L/4 = G $, add $G-L/4$ to both parts of the equation
if $G$ will be in the range between $0$ and $2*D$ answer is "yes", and "no" otherwise.
The overall time complexity of this approach is $O(1)$ per test case.
Setter's solution can be found here
Tester's solution can be found here
Please feel free to post comments if anything is not clear to you.
Author:Praveen Dhinwa
Tester:Istvan Nagy
Editorialist:Misha Chorniy
Simple
none
You are given matrix which presents a water reservoir, each cell can be water, air or brick. You need to check whether a state of the reservoir is stable or not? The state is stable if it will remain in the same state forever.
There are no water cells in matrix. We need to check if no one brick don't have air under itself. If brick has air under itself, it fall down.
ok = true
for i=1..n-1
for j=1..m
if s[i][j]=='B' and s[i+1][j]== 'A' //this block (i, j) will fall down
ok = false
Observe that air can't change something, we are interested in movements of bricks and water. Brick only can fall down, if under isn't brick. Water can move to the left(if there are empty or air), to the right(if there are empty or air) or move down(if there are nothing or air).
ok = true
for i=1..n
for j=1..m
if s[i][j]=='B' and i+1<=n and s[i+1][j]!='B' // brick (i, j) fall down
ok = false
if s[i][j]=='W'
if j==1 or j==m or i==n //water overflow bounds
ok = false
else if s[i][j-1]=='A' or s[i][j+1]=='A' or s[i+1][j]=='A' //water can move into adjacent blocks(left, right, down)
ok = false
Overall time complexity of this approach is $O(N*M)$.
Setter's solution can be found here
Please feel free to post comments if anything is not clear to you.
What is the differences between dynamic programming and greedy approach?
1)
You need to prepare food, for that you have a set of ingredients available. Each ingredient has its own health value. You need to write a code which can determine all possible combinations of ingredients whose sum of total health is highest in the end. The number of ingredients in any combination can be 3 ingredients. Given below is the list with ingredient and their health value.
Salt -1
Sugar +1
Onion +2
Tomato +1
Spinach +3
Oreo -2
For example: Spinach (+3), Onion (+2), Sugar(+1) have a total health value of 6 and number of ingredients are 3. Like this your program should find best combinations (print the 3 best ingredients).
2)You need to find smallest positive integer which has certain digits on a condition that if this integer is multiplied by 2,3,4,5 or 6, the answers will still have same digits.
For example: 125874 when multiplied by 2 gives 251748. Both numbers have same digits, i.e. 1, 2, 4, 5, 7 and 8
3)
Given two arrays of length n and n-1, all elements of both the arrays are same except one. Find the odd element out, giving O (1) solution.
Given two binary trees (not any special tree like binary search tree or red black tree) with n and n-1 nodes respectively, find the odd node out.
Given two binary search trees with n and n-1 nodes respectively with all elements same except one, find the odd node.
Given an array where each element signifies the number of cells which can be skipped, find the minimum number of steps taken to reach the last cell of the array. One has to start at index 0 and always move forward either by skipping cells by number given or by one.
How do we solve the KIRLAB Problem
Can anyone explain how to solve this problem.
Why am i getting runtime exception?
Author:Maksym Bevza
Tester:Arjun Arul
Editorialist:Misha Chorniy
Simple
none
You are given tree consisting $N$ nodes. Each node $i$ has value $P_{i}$ assigned to it. For each node $j$ find maximal value of node in the graph if to remove nodes adjacent to $j$ and $j$.
$N$ is less or equal than 10000. For each node will mark all nodes which are adjacent to it as dead(not usable), will find maximum value between non-marked nodes.
for i= 1..N
//Step 1
for j=1..N
alive[j] = 1; //initialize all marks as ones
//Step 2
alive[i] = 0; //mark itself as dead
for v is adjacent to i //mark all adjacent nodes
alive[v] = 0; //mark neighbours as dead
ans[i] = 0;
//Step 3
for j=1..N
if alive[j]==1 //if node j is alive
ans[i]= max(ans[i],p[j]); //find maximum value
How long it works? Obviously, the complexity of first and third step is $O(N)$, how to find the complexity of the second step? Denote $D(v)$ - degree of node $v$, for vertex $i$ complexity of step 2 is equal to $D(i)$, over all iterations complexity of second step is $D(1)$+$D(2)$+..+$D(N)$, what is $2*(N-1)$ for trees, we see that each edge using exactly two times. Total complexity of this algorithm is $O(N*N+2*(N-2)+N*N)$ = $O(N^2)$
First and third steps are slowest in the code above, how to optimize it? We can rewrite that code a bit.
for i=1..N
alive[i]=1;
for i=1..N
alive[i]=0;
for v is adjacent to i
alive[v] = 0;
ans[i]=0;
for j=1..N
if alive[j] == 1 //if node j is non-marked
ans[i] = max(ans[i],p[j]); //update answer
alive[i]=1;
for v is adjacent to i
alive[v] = 1;
Now total complexity is $O(N+2*(N-2)+N*N+2*(N-2))$ = $O(N^2)$, still $O(N^2)$, we can make some observations, basically we have multiset, where the following operations can be performed:
Let's use some data structure, namely in our case, the data structure which can add/erase elements, and find the maximal value in the set of these elements, but does this thing in time less than $O(N)$.
for i=1..N
add(P[i]);
for i=1..N
erase(P[i]);
for v is adjacent to i
erase(P[v]);
ans[i] = getMaximalValue();
add(P[i]);
for v is adjacent to i
add(P[v]);
What is the best data structure for this things? In most of the modern programming languages exists built-in data structures for such things, in C++ you can use multiset or map, Java has Map, Python has dictionaries. If your language doesn't have built-in data structures, you can read about heaps.
Let's write pseudocode with the map in C++, the similar code can be written in Java with Map or in Python with the dictionary.
map < int, int > F;
for i=1..N // Step 0
F[P[i]] += 1; //Initialize multiset
//Add element P[i] into mutliset, F[i] - maintain frequency of element i in mutliset
for i=1..N
//Step 1
F[P[i]] -= 1; //Erase exatly one occurence of P[i] from multiset
if (F[P[i]] == 0) //If some number frequency equal 0
F.erase(P[i]); //We erase it from multiset
for v is adjacent to i //Iterate over neighbours of node i
F[P[v]] -= 1;
if (F[P[v]] == 0)
F.erase(P[v]);
//Step 2
if !F.empty()
ans[v] = *F.rbegin();
//Step 3
F[P[i]] += 1;
for v is adjacent to i
F[P[v]] += 1;
Complexity of adding/erasing of number in such data structures is $O(log N)$, summary complexity of the first steps is $O(N log N)$, the same is for third steps, Total complexity is $O(N log N + N log N + N log N + N log N)$ = $O(N log N)$
The overall time complexity of this approach is $O(N log N)$.
Setter's solution can be found here
Tester's solution can be found here
Please feel free to post comments if anything is not clear to you.
Hi community,
Came across a simple piece of code to check if a given no is a power of 2. Thought of sharing it here , many may be aware of this though.
Method- 1
Suppose we have a no n and we want to check if its a power of 2.
if(!(n&n-1==0)) printf("power of zero!!!");
Explanation:
suppose n=8 (1000 in binary) then n-1=7 (0111);
1000
& 0111
= 0
if n=6
110& 101
= 0
Method 2:
Assuming n>0
if ((n & -n) == n) {
// n is a power of two
}
Edit- Have added Method 2 to check for it.
Edit 2- Some of the other methods for checking this can be found here. pow of 2 Edit 3- For detailed implementation check this link link text
Hope this helps. Happy coding ...
Author:Misha Chorniy
Tester:Istvan Nagy
Editorialist:Misha Chorniy
Medium
sweepline, binary search, polar angle, intersection of 2 circles
You are given $N$ points. Find minimal radius $R$ of the circle, which contains at least $K$ points inside or on the circumference.
$N$ is less or equal than 200. Well-optimized $O(N^4)$ can pass and $O(N^3 log (max(|X|,|Y|)/EPS))$ too. Describe $O(N^4)$ solution below.
Will call circle interesting if it contains at least one point from the $N$ points, and if we move this circle in any direction this circle will contain another set of points. Which circles are interesting? That circles which are constructed from 3 points(if they don't lie on the same line), or from 2 points(if segment which connects they are the diameter of the circle). We need to go over all interesting circles and check the number of points which lies inside of them.
Let's use next observation, if there are at least $K$ points lies inside a circle of the radius $R$, then at least $K$ points lies inside any circle with a radius bigger than $R$. Also if $K$ points don't lie inside the circle of $R$, then $K$ doesn't lie inside any circle with a radius smaller than $R$. The function of a radius is monotonic, we can use binary search for solving this problem. Rephrase problem, we have radius $R$, find a maximal number of points which lies inside of a circle with radius $R$ and compare it with $K$.
Use this observation for solving problem in $O(N^3 log (max(|X|, |Y|)/EPS))$
Will iterate over a pair of points $i$ and $j$, if the distance between them more than EPS, will try to carry out through them the circles(this points will lie on the circumference), there are exactly 2 circles which can be drawn between 2 distinct points. There are at most $2*N^2$ circles, and after building circles, iterate over all points and check if they lie inside of the circles in $O(1)$, hence $O(N^3)$ complexity for checking with radius $R$.
For this subtask use scanline approach and binary search by radius. The first step is binary search by radius, secondly iterate over point $i$ with coordinates ($X$,$Y$) which will lie on the circumference of the circle, then the center of the circle lies somewhere with coordinates ($X+R*cos(theta)$, $Y+R*sin(theta)$). For every point $j != i$ find all possible angles theta which satisfied condition that point j lies inside of circle of radius $R$ and centered in point ($X+R*cos(theta)$, $Y+R*sin(theta)$).
Let we have point $i$ and $j$ ($i != j$), how to find all theta's described above? At first, if $\\sqrt((X_{i}-X_{j})^2+(Y_{i}-Y_{j})^2)$ (Euclidian distance between point $i$ and $j$) more than $2*R$, there are no theta's satisfied condition. In another case, let's say that we have two circles of radius $R$ centered in points $i$ and $j$. Find points where they intersect, in every point of their intersection, can be placed a circle of the radius $R$, and it will contain both points $i$ and $j$. All theta's which satisfied condition lie within some sector of the circle centered in point $i$ and with the radius $R$.
Let's find intersection between two circles centered in points $i$ and $j$ with radiuses $R$. Call these points as $A$ and $B$(in case if circles intersect in one point, assume that $B$ = $A$). Let $P_{a}$ will be polar angle for vector $(A.x-X_{i}, A.y-Y_{i})$, and $P_{b}$ for vector $(B.x-X_{i}, B.y-Y_{i})$, possible two cases:
If theta lies inside the range $I$ then point $j$, will be inside the circle. Now we can reduce this problem to another well-known problem, there are segments, we need to find the point which covered with the maximal number of segments. It can be solved with standard sweep line technique.
The overall time complexity of this approach is $O(N^2 * log N * log (max(|X|,|Y|)/EPS))$.
Setter's solution can be found here
Tester's solution can be found here
Please feel free to post comments if anything is not clear to you.
Author:Kevin Charles Atienza
Tester:Istvan Nagy
Editorialist:Misha Chorniy
Hard
fft, number theory, inclusion-exclusion
You are given array $X$ consisting $N$ elements. All the elements in the input are integers. 2-dimensional array $Y$ is defined in next way, $Y_{i,j}$ = $X_{i} * X_{j}$ mod $359999$. Find number of integer tuples $a, b, c, d, e, f$, where gcd($Y_{a,b}$, $Y_{c,d}$, $Y_{e,f}$) = 1 modulo $10^9+7$. Denote that $gcd(0, 0) = 0$.
The first part of the solution is using not 2-dimensional array $Y$, instead of that calculate array $Z$ where $Z_{i}$ denotes the frequency of element $i$ in array $Y$, $i$ will be in a range between 0 and 359998. After that problem looks in a next way: we need to find the sum of all $Z_{i} * Z_{j} * Z_{k}$, where $gcd(i, j, k) = 1$.
$N$ is less or equal than 1000. Let's create array $Y$ in a naive way in $O(N^{2})$. Also, simply calculate array $Z$ in $O(N^{2})$.
A problem of the solution for subtask 1 in a too slow calculation of array $Y$, how to improve it? Let's consider number $359999$ in more detail, $359999 = 599 * 601$, both numbers $599$ and $601$ are primes. What can this fact give to us? Key observation: let we have a prime number $P$, from number theory follows next fact, any prime $P$ has primitive root $G$, in other words: For every $x$ = $1..P-1$, exists y, such $G^y$ = $x$, $0 <= y < (P-1)$.
Assume that we have the similar problem but with modulo $P$(not 359999), where $P$ is a prime number. Let's find the primitve root for P, call it G. Problem can be divided into two subproblems: where $X_{i}$ is zero or $X_{i}$ isn't zero. Because zero can't be represented using the primitive root of number $P$. $f(X)$ denoting such number that $G^{f(X)} = X$ and $ 0 <= f(X) < (P-1)$
$Y_{i,j}$ = $X_{i}$ * $X_{j}$ = $G^{f(X_{i})}$*$G^{f(X_{j})}$ = $G^{(f(X_{i}) + f(X_{j}))}$, in case if $X_{i} != 0$ and $X_{j} != 0$.
There are 4 subproblems:
zeroes = 0
for i = 1..N
if X[i] % P == 0
zeroes += 1
Z[0] = zeroes * zeroes +
zeroes * (N - zeroes) +
(N - zeroes) * zeroes
for i = 1..N
if X[i] mod P == 0
continue
for j=1..N
if X[j] mod P == 0
continue
da = f(X[i]) // G^da = X[i], 0<=da<(P-1)
db = f(X[j]) // G^db = X[j], 0<=db<(P-1)
dab = da + db // X[i]X[j] = G^(da+db)
Z[(G^dab)%P] += 1
How to calculate function $f$ in $O(1)$. Let's make some precomputations, $ff$[$G^i mod P$] = i, for i in the range between $0$ and $P-2$. $f(i)=ff[i]$. Let's rewrite this code a bit, namely precalculate $C_{i}$ - frequency of the number $i$ in the array $X$.
for i=1..N
if X[i]%P==0
C[X[i] % P] += 1
else
C[f(X[i])] += 1
Z[0] = C[0] * C[0] + 2 * C[0] * (N - C[0])
for i = 0..P-2
for j = 0..P-2
Z[(G^(i+j))%P] += C[i] * C[j]
What we see, last code is very similar to multiplication of two polynomials
for i = 1..N
for j = 1..M
C[i + j] += A[i] * B[j] //Standard multiplication of polynomials
Try to change the code above a bit
for i = 0..P-2
for j = 0..P-2
F[i + j] += C[i] * C[j]
for i = 0..2
(P-2)
Z[(G^i)%P] += F[i]
How to multiplicate two polynomials in way faster than $O(N^2)$, there are many algorithms, let's choose Fast Fourier Transform. Below pseudocode of multiplication using Fast Fourier Transform.
D = FFT(C)
for i = 0..2 * (P-2)
E[i] = D[i] * D[i]
F = inverseFFT(E)
for i = 0..2*(P-2)
Z[(G^i)%P] += F[i]
But we have two primes 599 and 601, what to do in this case? This solution can be modified for the case with two primes, find primitive roots for 599 and 601, let's call them $G$ and $H$.
Now every number between 0 and 359998 can be in one from the four types:
How to multiply two numbers from these types, we can multiply first and second components independently from each other. In other words: $(A,B)*(C,D)$=$(A*C mod 599, B*D mod 601)$ from Chinese Remainder Theorem Consider all possible multiplications from types:
First four convolutions can be processed in time $O(599 * 601) = O(359999)$, consider last convolution(it will be between two multipliers of fourth type):
$(X, Y) = (A, B) * (C, D)$ = $(G^{i1} mod 599, H^{j1} mod 601) * (G^{i2} mod 599, H^{j2} mod 601)$ = $(G^{i1+i2} mod 599, H^{j1+j2} mod 601)$
Let's create polynomial $P$, where $P$[$i * 2 * 601 + j$] is the number of numbers $G^{i}*H^{j} mod 359999$, if we'll multiply it by itself with FFT, we can take data of $(X, Y)$
$(i1 * 2 * 601 + j1)$ * $(i2 * 2 * 601 + j2)$ = $(i1 + i2) * 2 * 601 + (j1 + j2)$, $0 <= (j1 + j2) < 2 * 601$
for i = 0..598
for j = 0..600
P[i * 2 * 601 + j] += A[i][j] // number of numbers which represented in type G^i * H^j % 359999
fft(P)
for i = 0..(1<<21)-1
D[i] = P[i] * P[i] //Multiplying with FFT
Q[i] = inverseFFT(D)
for i = 0..4*359999
i12 = i / (2 * 601)
j12 = i % (2 * 601)
Z[G^(i12)%599 * H^(j12)%601] += Q[i]
After we'll find array $Z$ in fast way. How to speed up the following code:
ans=0
for i = 0..359999-1
for j = 0..359999-1
for k = 0..359999-1
if gcd(i, j, k) = 1
ans += Z[i] * Z[j] * Z[k]
ans %= 1000 * 1000 * 1000 + 7
Let's use some inclusion-exclusion, more precisely mobius-function, you can see this tutorial for similar problem:
But in this problem, we don't need to order $i, j, k$, therefore
for i = 1..359999
for j = i;j <= 359999; j+=i
D[i] += Z[j];
ans += mu[i] * D[i] * D[i] * D[i] //number of positive integer triplets, where each number is divisible by i multiplied by mobius-function from i
We forget about zeroes. How to count it:
ans = 3 * Z[1] * Z[0] * Z[0]
for i=1..359999
for j=i;j<=359999; j+=i
D[i]+=Z[j];
ans += mu[i] * D[i] * D[i] * D[i] //number of positive integer triplets, where each number is divisible by i multiplied by mobius-function from i
ans += 3 * mu[i] * D[i] * D[i] //Don't forget about multipling by 3
Overall time complexity of this approach is $O(2^{M} * M + X log X)$, where M = 21, X = 359999.
Setter's solution can be found here
Tester's solution can be found here
Please feel free to post comments if anything is not clear to you.