Quantcast
Channel: CodeChef Discuss - latest questions
Viewing all 39796 articles
Browse latest View live

User Account @ CodeChef

$
0
0

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

rashedcs


SRTX16E - Editorials

sorting of vectors or arrays

$
0
0

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>.

Swapping integers in one line

$
0
0

Is there any trick to sort the integers in just a line?

COLORING - Editorial

$
0
0

PROBLEM LINK:

Practice
Contest

Author:Sunny Aggarwal
Tester:Sergey Kulik
Editorialist:Sunny Aggarwal

DIFFICULTY:

Medium

PRE-REQUISITES:

Trees, Segment Trees, Implementation, Queries Handling, Data Structures.

PROBLEM STATEMENT:

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.

  • 1 X K Update the tree $T$ such that node $X$ becomes uncolored, all the nodes at distance $1$ from $X$ get colored with color $1$, all nodes at distance $2$ from $X$ get colored with color $2$, and so on up to nodes at distance $K$ from $X$. Formally, color all nodes that are at distance $(1 \le D \le K)$ units from node $X$ with color $D$ and make node $X$ colourless.

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$.

SOLUTION:

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$.

Complete Code Link.

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

  • At $0^{th}$ level in subtree rooted at $U$, we have to update nodes having number $[U \quad to \quad U]$ (i.e node $U$ only) with color $0$ ( $0$ denotes colorless ).
  • At $1^{st}$ level in subtree rooted at $U$, we have to update all nodes having number $[2 \times U \quad to \quad 2 \times U + 1]$ with color $1$.
  • At $2^{nd}$ level in subtree rooted at $U$, we have to update all nodes having number $[2 \times (2 \times U) \quad to \quad 2 \times (2 \times U + 1) + 1]$ with color $2$.
  • and so on upto min($K$, number of levels in subtree rooted at $U$).

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$.

Complete Code Link.

Please check the setter's solution for implementation details. Feel free to ask if anything is not clear.

TIME COMPLEXITY:

$O((\log_2{N})^3 \times Q)$

SETTER'S AND TESTER'S SOLUTION:

Setter's solution can be found here
Tester's solution can be found here

[Closed] Help Needed

$
0
0

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.

Inoi 2017 discussion

$
0
0

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

CHEFTRI4 - Editorial

$
0
0

PROBLEM LINK:

Contest
Practice

Author:Misha Chorniy
Tester:Tuan Anh Tran Dang
Translators:Sergey Kulik (Russian), Team VNOI (Vietnamese) and Hu Zecong (Mandarin)
Editorialist:Tuan Anh Tran Dang

DIFFICULTY

HARD

PREREQUISITE

NONE

PROBLEM

Check whether 4 triangles can be joined to create one single triangle.

SOLUTION

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.

2 triangles problem

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).

3 triangles problem

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.

sub-case 1

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:

  • (((1 + 2) + 3) + 4)
  • ((1 + 1) + 3 + 4) // Note that this is different with the previous case since we join 3 triangles (in which one is created from 1 and 2) at one time.
  • ((1 + 2) + (3 + 4))
  • ((1 + 2 + 3) + 4)

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.

sub-case 2

condition

    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

sub-case 3

condition

    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

sub-case 4

condition

    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.

AUTHOR'S AND TESTER'S SOLUTIONS:

setter
tester


January Long Challenge 2017 Schedule

$
0
0

Why there is no schedule of JAN17 posted till now?

CATSDOGS - Editorial

$
0
0

Practice
Contest

Author:Praveen Dhinwa
Tester:Istvan Nagy
Editorialist:Misha Chorniy

Difficulty:

Cakewalk

Pre-Requisites:

None

Problem Statement

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?

Explanation

Let's make some obvious observations:

  • Every cat has 4 legs.
  • Every dog has 4 legs.

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".

Subtask 1 and 2

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.

Subtask 3

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.

Solution:

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.

RESERVOI - Editorial

$
0
0

Practice
Contest

Author:Praveen Dhinwa
Tester:Istvan Nagy
Editorialist:Misha Chorniy

Difficulty:

Simple

Pre-Requisites:

none

Problem Statement

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.

Explanation

Subtask 1

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

Subtask 2 and 3

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)$.

Solution:

Setter's solution can be found here

Please feel free to post comments if anything is not clear to you.

Difference between dynamic programming and greedy approach.

$
0
0

What is the differences between dynamic programming and greedy approach?

interview question

$
0
0

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.

KIRLAB - Editorial

$
0
0

How do we solve the KIRLAB Problem

How to solve this problem based on strings and queries.


Why do I get a Runtime exception?

$
0
0

Why am i getting runtime exception?

CAPIMOVE - Editorial

$
0
0

Practice
Contest

Author:Maksym Bevza
Tester:Arjun Arul
Editorialist:Misha Chorniy

Difficulty:

Simple

Pre-Requisites:

none

Problem Statement

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$.

Explanation

Subtask 1 and 2

$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:

  • $alive_{i}=1$ is equivalent to adding in the multiset value of $p_{i}$
  • $alive_{i}=0$ is equivalent to erasing in the multiset value of $p_{i}$
  • Subtask 3

    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)$.

    Solution:

    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.

    Checking if a no is power of 2

    $
    0
    0

    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 ...

    CHEFCIRC - Editorial

    $
    0
    0

    Practice
    Contest

    Author:Misha Chorniy
    Tester:Istvan Nagy
    Editorialist:Misha Chorniy

    Difficulty:

    Medium

    Pre-Requisites:

    sweepline, binary search, polar angle, intersection of 2 circles

    Problem Statement

    You are given $N$ points. Find minimal radius $R$ of the circle, which contains at least $K$ points inside or on the circumference.

    Explanation

    Subtask 1

    $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$.

    Subtask 2

    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:

  • $P_{a} <= P_{b}$, then theta can lie in the range $I$ = [$P_{a}; P_{b}$]
  • $P_{a} > P_{b}$, then theta can lie in the range $I$ = [$P_{a}; 2*PI$) U [$0; P_{b}$]
  • 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))$.

    Solution:

    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.

    TUPLES - Editorial

    $
    0
    0

    Practice
    Contest

    Author:Kevin Charles Atienza
    Tester:Istvan Nagy
    Editorialist:Misha Chorniy

    Difficulty:

    Hard

    Pre-Requisites:

    fft, number theory, inclusion-exclusion

    Problem Statement

    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$.

    Explanation

    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$.

    Subtask 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})$.

    Subtask 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:

  • $0 * 0 = 0$
  • $0 * B = 0$, $B mod P > 0$
  • $A * 0 = 0$, $A mod P > 0$
  • $A * B = G^{f(A)} * G^{f(B)} = G^{f(A)+f(B)}$, $A mod P > 0, B mod P > 0$
  • 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:

  • (0, 0), only 0 satisfied this condition
  • ($G^i mod 599$, 0), only 598 numbers satisfied this condition
  • (0, $H^i mod 601$), only 600 numbers satisfied this condition
  • ($G^i mod 599$, $H^j mod 601$)
  • 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:

  • $(0, 0) = (0, 0) * (A, B)$ OR $(A, B) * (0, 0)$, $0 <= A <= 598, 0 <= B <= 600$
  • $(0, 0) = (0, A) * (B, 0)$ OR $(C, 0) * (0, D)$, $0 < A, D <= 598, 0 < B, C <= 600$
  • $(0, E) = (0, A) * (0, B)$ OR $(0, A) * (C, B)$ OR $(C, A) * (0, B)$, $0 < C <= 598, 0 < A, B, E <= 600$
  • $(E, 0) = (A, 0) * (B, 0)$ OR $(A, 0) * (B, C)$ OR $(A, C) * (B, 0)$, $0 < A, B, E <= 598$, $0 < C <= 600$
  • $(X, Y) = (A, B) * (C, D)$, $0 < A, C, X <= 598, 0 < B, D, Y <= 600$
  • 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:
  • $i = j = k = 0$, $gcd(i, j, k) = 0$, skip it
  • $i * j = 0$ OR $j * k = 0$ OR $i * k = 0$, we need to add $Z_{1} * Z_{0} * Z_{0}$
  • $i = 0$ OR $j = 0$ OR $k = 0$, we need to find the number of pairs $(a, b)$, where $gcd(Z_{a}, Z_{b}) = 1$ and multiply it by value of $Z_{0}$
  • 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.

    Solution:

    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.

    Viewing all 39796 articles
    Browse latest View live


    <script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>