Codeforces Round #654 (Div. 2) [D - Grid-00100] 题解

    技术2022-07-12  74

    [原题传送门]

    题意

    给你一个n和一个k,都为整数,需要你设计一个n*n的01矩阵,由0和1组成,该矩阵的和为k 同时规定,称该矩阵为 A A A m a x ( R ) max(R) max(R)为该矩阵的行之和最大值, m i n ( R ) min(R) min(R)为行之和的最小值 m a x ( C ) max(C) max(C)为该矩阵列之和的最大值, m i n ( C ) min(C) min(C)为列之和的最小值 f ( A ) = ( m a x ( R ) − m i n ( R ) ) 2 + ( m a x ( C ) − m i n ( C ) ) 2 f(A)=(max(R)-min(R))^2+(max(C)-min(C))^2 f(A)=(max(R)min(R))2+(max(C)min(C))2 要求输出矩阵A的最小f(A)及f(A)最小时的矩阵 A A A

    思路

    由于 f ( A ) f(A) f(A)的计算特性,需要每行每列都平均分到差不多的1 对于矩阵中的1 可以依照以下方式摆放: 先依照对角线摆放,当对角线摆满,下一个放在右上角的顶点,接下来,从第二行第一列开始,平行对角线向下摆,然后再从第一行第n-1列平行对角线向下摆,若还矩阵和还没到达k,就继续从第三行第一列向下摆……以此类推

    若按照这样摆,我们会发现,当k是n的倍数时(即k%n=0时),每行每列的1的个数都相同(如果不信可以自己画画 -v- ),而其他情况下,行和差与列和差也只是为1,因此 f ( A ) f(A) f(A)为2

    输入

    输入由多个测试用例组成。

    第一行包含一个整数t(1≤t≤100)。接下来的t行包含测试用例的描述。

    对于每个测试用例,只有一行包含两个整数n,k(1≤n≤300,0≤k≤n2)。

    保证所有测试用例的n2之和不超过105

    输出

    对于每个测试用例,首先打印满足条件的所有表中 f ( A ) f(A) f(A)的最小可能值。

    之后,打印n行包含n个字符。第i行中的第j个字符应等于 A i , j A_{i,j} Ai,j

    如果有多个答案,您可以打印任何答案。

    my Accepted code

    #include <algorithm> #include <cmath> #include <cstdio> #include <cstdlib> #include <cstring> #include <fstream> #include <iostream> #include <map> #include <queue> #include <set> #include <stack> #include <string> #define ll long long #define db double #define inf INT_MAX #define s(a, n) memset(a, n, sizeof(a)) #define rep(l, a, b) for (ll l = a; l < b; ++l) #define per(l, a, b) for (ll l = a; l >= b; --l) #define debug(a) cout << '#' << a << '#' << endl using namespace std; bool fi = true; const unsigned long long MOD = 1e9 + 7; int maps[305][305]; int main() { ios::sync_with_stdio(false); cin.tie(0), cout.tie(0); int t, n, k; cin >> t; while (t--) { if (fi) fi = !fi; else cout << endl; s(maps, 0); cin >> n >> k; int l = k % n; if (l == 0) cout << 0 << endl; else cout << 2 << endl; int s1 = 0, s2 = 0, c = 0, x1 = 0, x2 = n - 1; while (1) { for (int i = s1, j = s2; i < n && j < n && c < k; i++, j++, c++) { maps[i][j] = 1; } s1++; if (c >= k) break; for (int i = x1, j = x2; i < n && j < n && c < k; i++, j++, c++) { maps[i][j] = 1; } x2--; if (c >= k) break; } rep(i, 0, n) { cout << maps[i][0]; // rep(j, 1, n) { cout << ' ' << maps[i][j]; } rep(j, 1, n) { cout << maps[i][j]; } if (i != n - 1) cout << endl; // cout << endl; } } }

    ps.D题第一次交的时候思路没错,就是多输出了空格,调试了半个小时发现原因。原本可以拿1000+分。。结果最后只有860。在哭啊.jpg

    Processed: 0.011, SQL: 9