Week14HomeWork
A-
Q老师与石头剪刀布(必做) 签到题,不再赘述
B-
Q老师 得到一张 n 行 m 列的网格图,上面每一个格子要么是白色的要么是黑色的。
Q老师认为失去了 十字叉 的网格图莫得灵魂. 一个十字叉可以用一个数对 x 和 y 来表示, 其中 1 ≤ x ≤ n 并且 1 ≤ y ≤ m, 满足在第 x 行中的所有格子以及在第 y 列的 所有格子都是黑色的
例如下面这5个网格图里都包含十字叉
第四个图有四个十字叉,分别在 (1, 3), (1, 5), (3, 3) 和 (3, 5).
下面的图里没有十字叉
Q老师 得到了一桶黑颜料,他想为这个网格图注入灵魂。 Q老师 每分钟可以选择一个白色的格子并且把它涂黑。现在他想知道要完成这个工作,最少需要几分钟?
Input
第一行包含一个整数 q (1 ≤ q ≤ 5 * 10^4) — 表示测试组数
对于每组数据:
第一行有两个整数 n 和 m (1 ≤ n, m ≤ 5 * 10^4, n * m ≤ 4 * 10^5) — 表示网格图的行数和列数
接下来的 n 行中每一行包含 m 个字符 — '.' 表示这个格子是白色的, '*' 表示这个格子是黑色的
保证 q 组数据中 n 的总和不超过 5 * 10^4, n*m 的总和不超过 4 * 10^5
Output
答案输出 q 行, 第 i 行包含一个整数 — 表示第 i 组数据的答案
Example
9 5 5 ..*.. ..*.. ***** ..*.. ..*.. 3 4 **** .*.. .*.. 4 3 *** *.. *.. *.. 5 5 ***** *.*.* ***** ..*.* ..*** 1 4 **** 5 5 ..... ..*.. .***. ..*.. ..... 5 3 ... .*. .*. *** .*. 3 3 .*. *.* .*. 4 4 *.** .... *.** *.**
0 0 0 0 0 4 1 1 2
代码分析:
使用一维数组来储存矩阵,长宽为n,m ,index(i,j) = i*m+j 。每次记录每行每列‘*’的个数,选最大的几组存下来坐标,然后验证这个坐标的交叉处是不是‘*’ ,就可以得到答案了。
这道题其实不难,要注意的一点就是不能直接用二维数据存矩阵,因为oj上会超时,其实看数据范围也可以知道出题者的意图,0<n,m<1e4 ,而 0<n*m<5*1e5 ,哈哈,就是要卡一下你的内存。
但是这道题我wa了很多发,心态崩了,后来发现就是计算index的时候整错了一个数QAQ 。
#include<iostream> #include<cstdlib> #include<vector> #include<string> #include<cstring> using namespace std; #define maxn 40000010 struct Matrix { int n; int m; bool data[maxn + 100]; bool get(int i, int j) { return data[i*m + j]; } void change(int i, int j, char ch) { bool temp; if (ch == '*') {//黑色 temp = 1; } else { temp = 0; } data[i*m + j] = temp; } }; int q; Matrix Matr; int n, m; int main() { cin >> q; for (int ii = 0; ii < q; ii++) { //Matrix Matr; scanf("%d%d", &n, &m); Matr.n = n; Matr.m = m; memset(Matr.data,0,n*m); char temp; int sum1 = 0; int sum2 = 0; int tempxin = 0; int row; int col; vector<int> a, b; for (int i = 0; i < n; i++) { tempxin = 0; for (int j = 0; j < m; j++) { cin >> temp; Matr.change(i, j, temp); if (temp == '*') { tempxin++; } } //sum1 = max(tempxin, sum1); if (sum1 < tempxin) { sum1 = tempxin; row = i; a.clear(); a.push_back(i); } else if (sum1 == tempxin) { a.push_back(i); } } for (int j = 0; j < m; j++) { tempxin = 0; for (int i = 0; i < n; i++) { if (Matr.get(i, j) == 1) { tempxin++; } } if (sum2 < tempxin) { sum2 = tempxin; col = j; b.clear(); b.push_back(j); } else if (sum2 == tempxin) { b.push_back(j); } } bool flag = false; for (int i = 0; i < a.size(); i++) { for (int j = 0; j < b.size(); j++) { if (Matr.get(a[i], b[j]) == 0) { flag = true; break; } } } if (flag) { cout << n + m - sum1 - sum2 -1 << endl; } else { cout << n + m - sum1 - sum2 << endl; } } }
C --- 矩阵快速幂
Q老师 对数列有一种非同一般的热爱,尤其是优美的斐波那契数列。
这一天,Q老师 为了增强大家对于斐波那契数列的理解,决定在斐波那契的基础上创建一个新的数列 f(x) 来考一考大家。数列 f(x) 定义如下:
当 x < 10 时,f(x) = x;
当 x ≥ 10 时,f(x) = a0 * f(x-1) + a1 * f(x-2) + a2 * f(x-3) + …… + a9 * f(x-10),ai 只能为 0 或 1。
Q老师 将给定 a0~a9,以及两个正整数 k m,询问 f(k) % m 的数值大小。
聪明的你能通过 Q老师 的考验吗?
Input
输出文件包含多组测试用例,每组测试用例格式如下:
第一行给定两个正整数 k m。(k < 2e9, m < 1e5)
第二行给定十个整数,分别表示 a0~a9。
Output
对于每一组测试用例输出一行,表示 f(k) % m 的数值大小。
Sample Input
10 9999 1 1 1 1 1 1 1 1 1 1 20 500 1 0 1 0 1 0 1 0 1 0
Sample Output
45 104
这道题其实考的是矩阵快速幂这个知识点。
先贴上代码:
#include<iostream> #include<string> #include<cstring> using namespace std; int n = 10; int k; int m; struct Matrix{ int x[15][15]; Matrix(){ memset(x, 0, sizeof(x)); } Matrix operator*(Matrix t){ Matrix tem; for (int i = 0; i < n; i++){ for (int j = 0; j < n; j++){ tem.x[i][j] = 0; for (int k = 0; k < n; k++){ tem.x[i][j]=tem.x[i][j]+x[i][k]*t.x[k][j]%m; tem.x[i][j]=tem.x[i][j]%m; } } } return tem; } Matrix(const Matrix &t){ memcpy(x,t.x,sizeof(x)); } }; Matrix quick_pow(Matrix a, int x){ Matrix ret; for (int i = 0; i <= 9; i++) { ret.x[i][i] = 1; } while (x) { if (x & 1) ret = ret * a; a = a * a; x >>= 1; } return ret; } int main(){ int ans; while (cin >> k >> m){ Matrix a; ans = 0; for (int i = 0; i <= 9; i++){ cin >> a.x[0][i]; } for (int i = 1; i <= 9; i++){ a.x[i][i - 1] = 1; } if (k <= 9){ ans = k % m; }else if (k >= 10){ a = quick_pow(a, k - 9); for (int i = 0; i <= 9; i++){ ans += (a.x[0][i] * (9 - i)) % m; ans %= m; } } cout << ans << endl; } return 0; }