Constructing Tests CodeForces - 938C

本文解析了 CodeForces-938C 的问题,该问题是关于构造一个只包含0和1的最大矩阵,使得每m*m的子矩阵至少包含一个0。文章详细介绍了如何通过枚举因子来解决逆向问题,即已知最大1的数量x,找出对应的n和m。

CodeForces - 938C

Let’s denote a m-free matrix as a binary (that is, consisting of only 1’s and 0’s) matrix such that every square submatrix of size m × m of this matrix contains at least one zero.
Consider the following problem:
You are given two integers n and m. You have to construct an m-free square matrix of size n × n such that the number of 1’s in this matrix is maximum possible. Print the maximum possible number of 1’s in such matrix.
You don’t have to solve this problem. Instead, you have to construct a few tests for it.
You will be given t numbers x1, x2, …, xt. For every , find two integers ni and mi(ni ≥ mi) such that the answer for the aforementioned problem is exactly xi if we set n = ni and m = mi.

Input

The first line contains one integer t (1 ≤ t ≤ 100) — the number of tests you have to construct.
Then t lines follow, i-th line containing one integer xi (0 ≤ xi ≤ 109).
Note that in hacks you have to set t = 1.

Output

For each test you have to construct, output two positive numbers ni and mi (1 ≤ mi ≤ ni ≤ 109) such that the maximum number of 1’s in a mi-free ni × ni matrix is exactly xi. If there are multiple solutions, you may output any of them; and if this is impossible to construct a test, output a single integer  - 1.

Input

3
21
0
1

Output

5 2
1 1
-1

题意:

给出一个n * n的矩阵,让构建一个只包含01的矩阵,使得1的个数最多,并且每个m*m的矩阵至少包括一个0;现在给出1的个数x,让输出n m,如果不存在输出-1

思路:

先倒着想一下,比如给出n m,让你求出矩阵中1的个数最多是多少。
稍微想一下就知道0的个数应该是(n/m)*(n/m),那么1的个数就是(n * n)-(n/m) * (n/m);
那么现在就是判断这个方程等于x,是否有解。

因为方程是一个平方差,所以想到了平方差公式,把这个式子分解成了两个数相乘:
(n+n/m)*(n-n/m)=x

这时可以暴力枚举x的所有因子,进行求解。
假如x的两个因子分别为 a b,a=(n+n/m), b=(n-n/m).
明显:n/m=(a-b)/2;
则 n=a-n/m;
现在知道n以及n/m,求解m。
可以让temp=n/(n/m),判断n/temp是否等于n/m。
如果相等直接输出n temp,否则这两个因子没有解。

代码:

//#include<bits/stdc++.h>
#include<stdio.h>
#include<vector>
#include<math.h>
#include<string.h>
#include<iostream>
#include<algorithm>
#include<queue>
typedef long long ll;
using namespace std;
const int inf=0x3f3f3f3f;
typedef pair<int,int>p;
const int N=210000;

int main()
{
    ll t;
    scanf("%lld",&t);
    while(t--)
    {
        ll x;
        scanf("%lld",&x);
        if(x==0)
        {
            printf("1 1\n");
            continue;
        }
        ll flag=0;
        for(ll i=1; i<=(ll)sqrt(x); i++)
        {
            if(x%i==0&&(x/i-i)%2==0&&(x/i-i))
            {
                ll a=x/i;
                ll b=i;
                ll quo=(a-b)/2;
                ll n=a-quo;
                ll m=n/quo;
                if(n/m==quo)
                {
                    flag=1;
                    printf("%lld %lld\n",n,m);
                    break;
                }
            }
        }
        if(flag==0)
            printf("-1\n");
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值