/****************************************************************************************************************
* Author: Wang Jizhong
* Time:2016-4-11
*****************************************************************************************************************/
/*******************************************************************************************************************
* 问题:给定一个无限矩阵A,如下图所示,其中Aij=min(i,j)
* 1 1 1 1 1 1 1 1 1
* 1 2 2 2 2 2 2 2 2
* 1 2 3 3 3 3 3 3 3
* 1 2 3 4 4 4 4 4 4
* 1 2 3 4 5 5 5 5 5 ... y
* 1 2 3 4 5 6 6 6 6
* 1 2 3 4 5 6 7 7 7
* 1 2 3 4 5 6 7 8 8
* 1 2 3 4 5 6 7 8 9
* ⋮ ⋱
* x
* 希望你从中找到一个N*M的子矩阵,使得子矩阵中元素的和是K的整数倍
* 如果不存在这样的子矩阵,输出-1;否则输出子矩阵左上角元素的下标x和y。如果存在多个满足条件的子矩阵,输出x+y最小的一个;
* 如果仍有多个,输出其中x最小的一个。
***********************************************************************************************************************/
/**********************************************************************************************************************
* 实现思路: 过程中矩阵元素和以 所有(元素矩阵和)%K来表示;
* 假设存在N*M矩阵,左上角坐标为(x,y),则可认为左上角为(x-y,0)或者(0,y-x)沿着右下方向平移y步得到。
* 从左上角到向右下角平移1次,会导致矩阵中每个元素加1,导致平移后的矩阵元素和是(原来N*M矩阵元素和+N*M)%K,连续平移M次的结果与原来矩阵元素的结果相同,
* 故可把平移很多次的平移转化为0~K-1的平移,可以维持一个vector来保存平移n次的余数的变化,即:k*N*M%K,-1表示不可能得到这个数值
* 然后从左上角向下遍历,假设需要需求的矩阵式m*n,可从矩阵对称性知左上角坐标分别为(n-1,1)和(n,1)的n*m矩阵式相同的,故只考虑n次遍历即可,
* 在每次遍历中,我们得到矩阵的元素和,求的还差多少使得矩阵元素和为0,即为K的整数倍,然后根据vector查找平移多少步,消去那差值,如果为-1,代表不存在。
* 然后对列进行相同的遍历和查找,得到最终的结果.
************************************************************************************************************************/
//包含的库文件
#include
#include
using namespace std;
// 定义基本类型
typedef long long int64;
vector need;
int N, M, K, ansX, ansY;
// 更新坐标
void Update(int x, int y) {
if (ansX == -1)ansX = x, ansY = y;
else if (ansX + ansY > x + y) ansX = x, ansY = y;
else if (ansX + ansY == x + y && x < ansX) ansX = x,ansY = y;
}
// 获取到第i(row)行,前j(len)列的和
int64 Getsum(int row, int len) {
if (len <= row) return ((int64)1 + len)*len / 2;
return ((int64)1 + row)*row / 2 + (int64)1 *(len - row)*row;
}
// 函数功能:寻找矩阵
void Search_matrix(int n, int m, bool tran) {
int64 sum = 0;
for (int i = 0; i <= m; i++) sum = (sum + Getsum(i, n)) % K; // 左上角n行m列的值
// 向下遍历n行,由列数决定
for (int start = 1; start <= n; start++) {
int r = (K - sum) % K; // 还需要多少能够达到K的整数倍
if (need[r] != -1) {
int x = need[r] + 1; int y = start + need[r];
if (tran)swap(x, y);
Update(x, y);
}
sum = ((sum - Getsum(start, n)) % K + Getsum(start + m, n) % K + K) % K; // 加K防止产生负数对K求模;
}
}
// 功能,实现子矩阵求和是K的整数倍
void Search_pos() {
// 初始化need 数组
need.assign(K + 1, -1);
int u = 0; need[u] = 0;
while (true) {
int nu = ((int64)1 * N * M + u) % K;
if (need[nu] != -1) break;
need[nu] = need[u] + 1;
u = nu;
}
ansX = -1; ansY = -1;
Search_matrix(N, M, false); // 行搜索
Search_matrix(M, N, true); // 列搜索
}
// 主程序函数
int main() {
ios::sync_with_stdio(false);
int Q = 0; cin >> Q;
while (Q--) {
cin >> N >> M >> K;
Search_pos();
if (ansX == -1) cout << -1 << endl;
else cout << ansX << " " << ansY << endl;
}
return 0;
}