Grid L – Codeforces Round 1093 (Div. 2)

Problem Summary
Roger has:
- straight unit segments
- 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 .
A grid contains:
-
Horizontal edges:
-
Vertical edges:
So the total number of unit edges in the grid is:
Available edges are:
So we must satisfy:
If no such exist, output .

Main Observation
Starting from:
Multiply by and add :
Left side becomes:
But:
So we get the identity:
Let:
Then the problem becomes:
Divisor Transformation
If we find divisors and such that:
Then:
So:
Since is always odd, its divisors are also odd, meaning and are always divisible by .
So the task becomes:
Find any divisor pair of giving positive integers .
Extra Constraint (Important)
Even if the total number of edges matches, we must also ensure we can place all L-shaped pieces.
Each L-piece consumes:
- horizontal edge
- vertical edge
So we need:
and
Where:
If either fails, then this is not valid.
Algorithm Used in the Code
For each test case:
- Read
- Compute:
-
Find divisors of by looping from to (only odd divisors)
-
Store divisor candidates inside a linked list
-
For each divisor in the list:
- Compute
- Compute:
- Compute and
- Check if and
- If found, print and
- Otherwise print
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 pairs
So it matches the structure: InsertAtEnd(), diviseurs(), tempNode, etc.
Complexity Analysis
We search divisors up to:
And:
So:
This is very fast.
- Time complexity: per test case
- Memory complexity: where 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:
into the factorized form:
Then it becomes a divisor search problem.
After getting , we must also verify that the L-shaped pieces fit:
This is the full reasoning behind the solution.