Logo
Overview
Grid L – Codeforces Round 1093 (Div. 2) Writeup

Grid L – Codeforces Round 1093 (Div. 2) Writeup

April 22, 2026
4 min read

Grid L – Codeforces Round 1093 (Div. 2)

Alt text

Problem Summary

Roger has:

  • pp straight unit segments
  • qq L-shaped pieces (each L uses 2 unit segments, one horizontal and one vertical)

He wants to use all pieces to build a rectangular grid of size n×mn \times m.

A grid n×mn \times m contains:

  • Horizontal edges: H=m(n+1)H = m(n+1)

  • Vertical edges: V=n(m+1)V = n(m+1)

So the total number of unit edges in the grid is:

H+V=m(n+1)+n(m+1)=2nm+n+mH + V = m(n+1) + n(m+1) = 2nm + n + m

Available edges are:

p+2qp + 2q

So we must satisfy:

2nm+n+m=p+2q2nm + n + m = p + 2q

If no such n,mn, m exist, output −1-1.

Alt text


Main Observation

Starting from:

2nm+n+m=p+2q2nm + n + m = p + 2q

Multiply by 22 and add 11:

2(2nm+n+m)+1=2(p+2q)+12(2nm + n + m) + 1 = 2(p + 2q) + 1

Left side becomes:

4nm+2n+2m+14nm + 2n + 2m + 1

But:

(2n+1)(2m+1)=4nm+2n+2m+1(2n+1)(2m+1) = 4nm + 2n + 2m + 1

So we get the identity:

(2n+1)(2m+1)=2(p+2q)+1(2n+1)(2m+1) = 2(p + 2q) + 1

Let:

S=2(p+2q)+1S = 2(p + 2q) + 1

Then the problem becomes:

(2n+1)(2m+1)=S(2n+1)(2m+1) = S

Divisor Transformation

If we find divisors aa and bb such that:

a⋅b=Sa \cdot b = S

Then:

2n+1=a,2m+1=b2n+1 = a,\quad 2m+1 = b

So:

n=a−12,m=b−12n = \frac{a-1}{2}, \quad m = \frac{b-1}{2}

Since SS is always odd, its divisors are also odd, meaning (a−1)(a-1) and (b−1)(b-1) are always divisible by 22.

So the task becomes:

Find any divisor pair (a,b)(a,b) of SS giving positive integers n,mn,m.


Extra Constraint (Important)

Even if the total number of edges matches, we must also ensure we can place all qq L-shaped pieces.

Each L-piece consumes:

  • 11 horizontal edge
  • 11 vertical edge

So we need:

q≤Hq \le H

and

q≤Vq \le V

Where:

H=m(n+1),V=n(m+1)H = m(n+1), \quad V = n(m+1)

If either fails, then this (n,m)(n,m) is not valid.


Algorithm Used in the Code

For each test case:

  1. Read p,qp, q
  2. Compute:
S=2(p+2q)+1S = 2(p + 2q) + 1
  1. Find divisors of SS by looping from 33 to S\sqrt{S} (only odd divisors)

  2. Store divisor candidates inside a linked list

  3. For each divisor aa in the list:

    • Compute b=S/ab = S/a
    • Compute:
n=a−12,m=b−12n = \frac{a-1}{2}, \quad m = \frac{b-1}{2}
  • Compute HH and VV
  • Check if q≤Hq \le H and q≤Vq \le V
  1. If found, print nn and mm
  2. Otherwise print −1-1

Why Use a Linked List Here?

Normally, you could just check divisor pairs directly.

But in this solution we kept the same skeleton:

  • store divisor candidates inside a linked list
  • traverse the linked list to test possible (a,b)(a,b) pairs

So it matches the structure: InsertAtEnd(), diviseurs(), tempNode, etc.


Complexity Analysis

We search divisors up to:

S\sqrt{S}

And:

S=2(p+2q)+1≤2(108+2⋅108)+1≈6⋅108S = 2(p + 2q) + 1 \le 2(10^8 + 2\cdot 10^8) + 1 \approx 6\cdot 10^8

So:

S≈24500\sqrt{S} \approx 24500

This is very fast.

  • Time complexity: O(S)O(\sqrt{S}) per test case
  • Memory complexity: O(k)O(k) where kk is the number of stored divisors

Final C Code

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
typedef struct Node{
int value;
struct Node *next;
}Node;
typedef Node* NodePtr;
void PrintList(NodePtr head)
{
while(head)
{
printf("value %d\n",head->value);
head=head->next;
}
}
int InsertAtEnd(NodePtr *ptrHead,int value)
{
NodePtr head=*ptrHead;
NodePtr tempNode=(NodePtr)malloc(sizeof(Node));
if(!tempNode) return -1;
tempNode->value=value;
tempNode->next=NULL;
if(head==NULL)
{
*ptrHead=tempNode;
return 1;
}
while(head->next!=NULL) head=head->next;
head->next=tempNode;
return 1;
}
NodePtr diviseurs(NodePtr head,int number)
{
for(int i=3;i<=sqrt(number);i+=2)
{
if(number%i==0)
{
InsertAtEnd(&head,i);
int other=number/i;
if(other!=i) InsertAtEnd(&head,other);
}
}
return head;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int p,q;
scanf("%d %d",&p,&q);
int S=2*(p+2*q)+1;
NodePtr head=NULL;
head=diviseurs(head,S);
NodePtr tempNode=head;
int n=-1,m=-1;
int found=0;
while(tempNode!=NULL)
{
int a=tempNode->value;
int b=S/a;
if((a-1)%2==0 && (b-1)%2==0)
{
n=(a-1)/2;
m=(b-1)/2;
int H=m*(n+1);
int V=n*(m+1);
if(q<=H && q<=V)
{
found=1;
break;
}
}
tempNode=tempNode->next;
}
if(found) printf("%d %d\n",n,m);
else printf("-1\n");
}
return 0;
}

Takeaways

The trick is transforming:

2nm+n+m=p+2q2nm + n + m = p + 2q

into the factorized form:

(2n+1)(2m+1)=2(p+2q)+1(2n+1)(2m+1) = 2(p+2q)+1

Then it becomes a divisor search problem.

After getting (n,m)(n,m), we must also verify that the qq L-shaped pieces fit:

q≤H,q≤Vq \le H,\quad q \le V

This is the full reasoning behind the solution.