A Madoka and Math Dad
题意:给出一个数,用1~9的数字的总和等于这个数,并将需要拼的数字组成一个新的数,并要求相邻的数字不相同,如5只能拼出212(最大),4只能用121拼出(不能用211,11相邻了)
一开始以为暴搜,写完发现50都跑不出来,别说1000了,才想到我这是每一次遍历都要找9个值,时间复杂度太大了。
贪心!然后贪心思路发现,要想要数字最大,虽然让位数最高的数最大,但敌不过位数的比较,位数多了数自然就大了,位数想要越多,每一位的数就得越小,而且由于相邻的两数不能相同,则所有的数都用1和2拆出来,这样数就最大了。
有两个式子,x为2的个数,y为1的个数
2*x + y = n
x = y + 1或者x = y 或者x = y - 1(1和2的个数顶多查一个)
#include <bits/stdc++.h>
using namespace std;
int main()
{
int t;
cin >> t;
while(t -- )
{
int n; cin >> n;
if(n == 1 || n == 2) {cout << n << endl; continue;}
int one = 0, two = 0;
if((n + 1) % 3 == 0) two = (n + 1) / 3, one = (n - 2) / 3;
else if((n - 1) % 3 == 0) two = (n - 1) / 3, one = (n + 2) / 3;
else two = n / 3, one = n / 3;
while(one || two)
{
if(two >= one){
if(two) two -- , cout << 2;
if(one) one --, cout << 1;
}
else {
if(one) one --, cout << 1;
if(two) two -- , cout << 2;
}
}
cout << endl;
}
return 0;
}
B Madoka and the Elegant Gift
题意:给出01二维矩阵,1为黑色,0为白色,其子矩阵的定义为子矩阵的值都是1,判断二维矩阵中的子矩阵是否有相交,若没有(可包含)则输出YES,否则输出NO。
解法:(麻烦解法)从第一个块开始遍历,如果为1,则从该点找行和列能”构成子矩阵”的行和列(不一定),再判断这个“子矩阵”中是否都是1,然后在判断这个子矩阵左和上是否有之前的子矩阵,如果相邻则肯定有相交的地方。
#include <bits/stdc++.h>
using namespace std;
const int N = 110;
bool g[N][N];
char a[N][N];
int main()
{
int t; cin >> t;
while(t -- )
{
int n, m; cin >> n >> m;
memset(g, 0, sizeof g);
memset(a, 0, sizeof a);
for(int i = 1; i <= n; i ++ )
for(int j = 1; j <= m; j ++ )
cin >> a[i][j];
int st = false;
for(int i = 1; i <= n; i ++ ){
for(int j = 1; j <= m; j ++ ){
if(a[i][j] == '1' && !g[i][j]){
int row = i, col = j;
g[row][col] = true;
while(a[i][col + 1] == '1') g[i][col + 1] = true, col ++;
while(a[row + 1][j] == '1') g[row + 1][j] = true, row ++;
for(int x = i + 1; x <= row; x ++ ){
for(int y = j + 1; y <= col; y ++ ){
if(a[x][y] == '0') st = true;
g[x][y] = true;
}
if(st) break;
}
if(st) break;
for(int x = j; x <= col; x ++ )
if(g[i - 1][x]) {st = true; break;}
for(int y = i; y <= row; y ++ )
if(g[y][j - 1]) {st = true; break;}
}
}
if(st) break;
}
if(st) cout << "NO" << endl;
else cout << "YES" << endl;
}
return 0;
}
但起始不需要那么麻烦,全部遍历一遍,若为黑块,则判断以其为起点的2
∗
*
∗ 2小矩阵是否都是1,若不是则输出NO,否则遍历完输出YES。
要遍历2
∗
*
∗ 2的小矩阵的原因为最后形成的为子矩阵,四四方方的,如果两子矩阵有相交的地方则为一定唯有上述子矩阵不全为1的情况。
大佬的解释
#include"bits/stdc++.h"
#define all(x) x.begin(),x.end()
#define len(x) x.size()
#define INF (1e9)
#define vi vector<int>
#define ll long long
#define db double
#define vvi vector<vector<int>>
using namespace std;
void solve() {
int n, m;
cin >> n >> m;
vvi a(n + 1, vi(m + 1));
for (int i = 1; i <= n; i++) {
string temp;
cin >> temp;
for (int j = 0; j < m; j++) {
a[i][j + 1] = temp[j] - '0';
}
}
for (int i = 1; i < n; i++) {
for (int j = 1; j < m; j++) {
int sum = a[i][j] + a[i][j + 1] + a[i + 1][j] + a[i + 1][j + 1];
if (sum == 3) {
cout << "NO" << endl;
return;
}
}
}
cout << "YES" << endl;
}
int main() {
int n;
cin >> n;
while(n--) {
solve();
}
return 0;
}
C Madoka and Childish Pranks
题意,给出一个01二维矩阵,通过下面的图形尝试拼出所给的01矩阵,注意后图画的地方会覆盖先图画的地方。若不能拼出,则输出-1,若能拼出,输出需要操作的次数(不要求操作的次数最少,能凑出就行),后面再输出操作的左上角和右下角的坐标,即答案不唯一。
样例1
01000
10100
01010
00110
贪心,重点是要求题目操作的次数不要求最小值,所以可以一个黑块一个黑块的涂,通过第一个样例给我了灵感,可以通过01(可以横着也可以竖着)这样的小块去拼出这个01矩阵,即有多少个黑块就有多少个操作(输出-1的情况为第一行第一列的块为黑色,不能通过下图的两个拼出)。
还需要注意的是第一列黑色方块只能通过第一个进行拼出。
想要拼出这种,如果按从小到大的顺序拼,后面黑色的会将前面黑色的方块覆盖,所以遍历的时候需要从后向前输出
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
const int N = 110;
char a[N][N];
vector<pair<int, int> > v;
int main()
{
int t; cin >> t;
while(t -- )
{
int n, m; cin >> n >> m;
v.clear();
for(int i = 1; i <= n; i ++ )
for(int j = 1; j <= m; j ++ )
cin >> a[i][j];
if(a[1][1] == '1') { cout << -1 << endl; continue; }
int cnt = 0;
for(int i = n; i >= 1; i -- )
for(int j = m; j >= 1; j -- )//从后向前输出
if(a[i][j] == '1') cnt ++, v.push_back({i, j});
cout << cnt << endl;
for(int i = 0; i < v.size(); i ++ )
{
pair<int, int> p = v[i];
if(p.second == 1) {
cout << p.first - 1 << ' ' << p.second << ' ' << p.first << " " << p.second << endl;
}
else cout << p.first << ' '<< p.second - 1 << ' ' << p.first << ' ' << p.second << endl;
}
}
return 0;
}
D Madoka and the Best School in Russia
参照大佬讲解
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int x, d, k;
bool check(int n)
{
if(n < 4) return 1;
if(n % 2 == 0 || n % 3 == 0) return 0;
for(int i = 5; i * i <= n; i += 6)
if(n % i == 0 || n % (i + 2) == 0) return 0;
return 1;
}
int main()
{
int t; cin >> t;
while(t -- )
{
k = 0;
cin >> x >> d;
while(x % d == 0) k ++, x /= d;
// cout << k << endl;
if(k < 2) cout << "NO" <<endl;
else if(!check(x)) cout << "YES" <<endl;//s是合数
else if(check(d))cout << "NO" << endl;//s不是合数,d是质数
else printf(k > (x * x == d) + 2 ? "YES\n" : "NO\n");
}
return 0;
}