Codeforces 938C

传送门:http://codeforces.com/contest/938/problem/C

给定两个正整数n,m(m≤n),对于一个n阶0-1方阵,其任意m阶子方阵中至少有一个元素“0”,则可以求解这个方阵中的“1”的最大数目。现求解这个问题的逆向问题:已知这个最大数目为X,求相应的nm

由原问题可以得到方程:$n^2-leftlfloorfrac{n}{m} ight floor^2=Xcdots(1)$,于是,对于给定的X,求解不定方程(1)。

令$k=leftlfloorfrac{n}{m} ight floor$,则$leftlfloorfrac{n}{k+1} ight floor<leftlfloorfrac{n}{k} ight floor$时,$leftlfloorfrac{n}{m} ight floor=kRightarrow klefrac{n}{m}<k+1Rightarrow frac{n}{k+1}<mlefrac{n}{k}Rightarrow m=leftlfloorfrac{n}{k} ight floor$;于是,原方程化为$n^2-k^2=XRightarrow (n+k)(n-k)=Xcdots(2)$。

①若X=0,显然n=k,其中的一组解为n=1,m=1;

②若X≠0,则将X分解,设X=a·b(b<a)。

则解不定方程:$u^2-v^2=abRightarrow u=frac{a+b}{2},v=frac{a-b}{2}$。

于是,方程(2)可能有解n=u,k=v

于是,当uv均为正整数,且$leftlfloorfrac{u}{v+1} ight floor<leftlfloorfrac{u}{v} ight floor$时,方程(1)有解:$n=u,m=leftlfloorfrac{u}{v} ight floor$。

参考程序如下:

#include <stdio.h>

int main(void)
{
    int t;
    scanf("%d", &t);
    while (t--) {
        int x;
        int n = -1, m = -1;
        scanf("%d", &x);
        if (x == 0) {
            n = 1;
            m = 1;
        }
        else {
            for (int i = 1; i * i < x; i++) {
                int j = x / i;
                if (x == i * j && !((i ^ j) & 1)) {
                    int u = (j + i) / 2;
                    int v = (j - i) / 2;
                    if (u / v - u / (v + 1) > 0) {
                        n = u;
                        m = u / v;
                        break;
                    }
                }
            }
        }
        if (n == -1) printf("-1
");
        else printf("%d %d
", n, m);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/siuginhung/p/8454646.html