传送门:http://codeforces.com/contest/938/problem/C
给定两个正整数n,m(m≤n),对于一个n阶0-1方阵,其任意m阶子方阵中至少有一个元素“0”,则可以求解这个方阵中的“1”的最大数目。现求解这个问题的逆向问题:已知这个最大数目为X,求相应的n和m。
由原问题可以得到方程:$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。
于是,当u、v均为正整数,且$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; }