牛客小白月赛31 [ C,D,G,H,I ] 题解报告

[原题传送门]

C.图像存储

题目

数字图像是一个由“0”和“1”这两个元素组成的矩阵,除去边角上的元素,每个元素都有上下左右相邻的四个元素。再一个数字图像中,元素“0”代表空白,只有元素“1”所在的位置才有一个黑点。由此,一副黑白的图像得以显现。

为了能在更少的空间里存储更多的图像,一个可行的办法就是每种相同的黑块只保留一个,其他的地方只保留位置,这样便实现了压缩。查看时,只需将保留的黑块拓印到其它的位置,这样就实现了图像的复原。

可见,该技术的关键就是对不同的黑块进行记录。我们把由若干个相邻的“1”构成的区域定义为黑块,规定一个孤立的“1”也是一个黑块,黑块中“1”的个数为黑块的大小,通过上下左右平移可以实现重合并且等大的黑块为同一种黑块。现在你的任务是分别算出一个图像中黑块的个数和种数。

思路

dfs搜索黑块,对dfs搜索路径进行双哈希,素数最好开大点
在这里插入图片描述

Accepted code

/*
 * @Autor: CofDoria
 * @Date: 2021-01-10 21:48:38
 * @LastEditTime: 2021-01-11 02:35:25
 */
// #include <bits/stdc++.h>
#include <algorithm>
#include <cstdio>
#include <cstring>
using namespace std;

#define db double
#define ll long long
#define inf 0x3f3f3f3f
#define s(a, n) memset(a, n, sizeof(a))
#define debug(a) cout << '#' << a << '#' << endl
#define rep(l, a, b) for (register ll l = a; l < b; ++l)
#define per(l, a, b) for (register ll l = a; l >= b; --l)
#define _ios ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
#define _forit(i, c) \
    for (__typeof__((c).begin()) i = (c).begin(); i != (c).end(); ++i)

bool fi = true;
const unsigned long long MOD = 1e9 + 7;

inline ll gcd(ll a, ll b) {
    
     return (b == 0 ? a : gcd(b, a % b)); }

int mp[1005][1005];
int vis[1005][1005];

ll a[1000005];

int st[4][2] = {
    
    {
    
    0, 1}, {
    
    0, -1}, {
    
    1, 0}, {
    
    -1, 0}};

int n, m;
int cnt = -1;

void dfs(int i, int j, int c) {
    
    
    vis[i][j] = 1;
    for (int x = 0; x < 4; x++) {
    
    
        int ii = i + st[x][0];
        int jj = j + st[x][1];
        if (ii >= 0 && ii < n && jj >= 0 && jj < m && !vis[ii][jj] &&
            mp[ii][jj]) {
    
    
            a[c] = (a[c] * 131 % MOD + x*1007) % MOD;
            dfs(ii, jj, c);
        }
        // 如果不明白这里为何要哈希 结合上图理解
        a[c] = (a[c] * 131 % MOD + 31) % MOD;
    }
    return;
}

int main() {
    
    
    // freopen("in.txt", "r", stdin);
    // freopen("out.txt", "w", stdout);
    while (~scanf("%d%d", &n, &m) && n && m) {
    
    
        memset(a, 0, sizeof(a));
        memset(vis, 0, sizeof(vis));
        cnt = -1;
        for (int i = 0; i < n; i++) {
    
    
            char s[10005];
            scanf("%s", s);
            for (int j = 0; j < m; j++) {
    
    
                mp[i][j] = s[j] - '0';
                // vis[i][j] = 0;
            }
        }
        for (int i = 0; i < n; i++) {
    
    
            for (int j = 0; j < m; j++) {
    
    
                if (mp[i][j] == 1 && !vis[i][j]) dfs(i, j, ++cnt);
            }
        }
        sort(a, a + cnt + 1);
        printf("%d %d\n", cnt + 1, unique(a, a + cnt + 1) - a);
    }
    // fclose(stdin);
    // fclose(stdout);
    return 0;
}

D.坐标计数

题目

定义一个坐标变换,坐标 (x,y) 变换后变为 ( x ⊕ y x \oplus y xy, ∣ x − y ∣ |x-y| xy)。

给定一片矩形区域,计算区域内有多少个整数点在经过有限次变换后变为 ( 0 , 0 ) (0,0) (0,0)

思路

经过本地模拟打表后,发现所有点都可以在100次运算之内变为 ( 0 , 0 ) (0,0) (0,0)。注意点数需要开 l o n g l o n g long long longlong

Accepted code

/*
 * @Autor: CofDoria
 * @Date: 2021-01-10 20:43:31
 * @LastEditTime: 2021-01-10 21:18:46
 */
#include <bits/stdc++.h>
using namespace std;

#define db double
#define ll long long
#define inf 0x3f3f3f3f
#define s(a, n) memset(a, n, sizeof(a))
#define debug(a) cout << '#' << a << '#' << endl
#define rep(l, a, b) for (register ll l = a; l < b; ++l)
#define per(l, a, b) for (register ll l = a; l >= b; --l)
#define _ios ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
#define _forit(i, c) \
    for (__typeof__((c).begin()) i = (c).begin(); i != (c).end(); ++i)

bool fi = true;
const unsigned long long MOD = 1e9 + 7;

inline ll gcd(ll a, ll b) {
    
     return (b == 0 ? a : gcd(b, a % b)); }

bool f(int a, int b, int d) {
    
    
    if (d > 100) return false;
    if ((a ^ b) == 0 && abs(a - b) == 0)
        return true;
    else
        return f((a ^ b), abs(a - b), d + 1);
}

int main() {
    
    
    // freopen("in.txt", "r", stdin);
    // freopen("out.txt", "w", stdout);
    int t;
    ll a1, a2, b1, b2;
    cin >> t;
    while (t--) {
    
    
        cin >> a1 >> b1 >> a2 >> b2;
        cout << (a2 - a1 + 1) * (b2 - b1 + 1) << endl;
    }
    // fclose(stdin);
    // fclose(stdout);
    return 0;
}

G.简单题的逆袭

题目

给定x,y,找出满足方程 x k ≤ y x^k \le y xky 的最大的k

思路

特判:当x小于2且x比y小时,k为无穷,当y为0时,k不存在;其他情况暴力求解,注意范围可能爆 l o n g l o n g long long longlong

Accepted code

/*
 * @Autor: CofDoria
 * @Date: 2021-01-10 20:18:40
 * @LastEditTime: 2021-01-10 20:41:49
 */
#include <bits/stdc++.h>
using namespace std;

#define db double
#define ll long long
#define inf 0x3f3f3f3f
#define s(a, n) memset(a, n, sizeof(a))
#define debug(a) cout << '#' << a << '#' << endl
#define rep(l, a, b) for (register ll l = a; l < b; ++l)
#define per(l, a, b) for (register ll l = a; l >= b; --l)
#define _ios ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
#define _forit(i, c) \
    for (__typeof__((c).begin()) i = (c).begin(); i != (c).end(); ++i)

bool fi = true;
const unsigned long long MOD = 1e9 + 7;

inline ll gcd(ll a, ll b) {
    
     return (b == 0 ? a : gcd(b, a % b)); }

ll f(__int128_t a, __int128_t b) {
    
    
    ll x = 0;
    __int128_t m = a;
    while (m <= b) {
    
    
        x++;
        m *= a;
    }
    return x;
}

int main() {
    
    
    // freopen("in.txt", "r", stdin);
    // freopen("out.txt", "w", stdout);
    long long x, y;
    int t;
    cin >> t;
    while (t--) {
    
    
        cin >> x >> y;
        if (x == 0 || (x == 1 && y) || y == 0) {
    
    
            cout << -1 << endl;
        } else {
    
    
            cout << f(x, y) << endl;
        }
    }
    // fclose(stdin);
    // fclose(stdout);
    return 0;
}

H.对称之美

题目

给出n个字符串,从第1个字符串一直到第n个字符串每个串取一个字母来构成一个新字符串,新字符串的第i个字母只能从第i行的字符串中选出,这样就得到了一个新的长度为n的字符串,请问这个字符串是否有可能为回文字符串?

思路

暴力求对称的两个字符串有没有相同的字符

Accepted code

/*
 * @Autor: CofDoria
 * @Date: 2021-01-10 19:44:44
 * @LastEditTime: 2021-01-10 20:00:15
 */
#include <bits/stdc++.h>
using namespace std;

#define db double
#define ll long long
#define inf 0x3f3f3f3f
#define s(a, n) memset(a, n, sizeof(a))
#define debug(a) cout << '#' << a << '#' << endl
#define rep(l, a, b) for (register ll l = a; l < b; ++l)
#define per(l, a, b) for (register ll l = a; l >= b; --l)
#define _ios ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
#define _forit(i, c) \
    for (__typeof__((c).begin()) i = (c).begin(); i != (c).end(); ++i)

bool fi = true;
const unsigned long long MOD = 1e9 + 7;

inline ll gcd(ll a, ll b) {
    
     return (b == 0 ? a : gcd(b, a % b)); }

string s[100];
int m[100][35];
int t;
int n;

int main() {
    
    
    // freopen("in.txt", "r", stdin);
    // freopen("out.txt", "w", stdout);
    cin >> t;
    while (t--) {
    
    
        cin >> n;
        memset(m, 0, sizeof(m));
        for (int i = 0; i < n; i++) {
    
    
            cin >> s[i];
            for (int sz = s[i].size(), j = 0; j < sz; ++j) {
    
    
                m[i][s[i][j] - 'a']++;
            }
        }
        for (int i = 0; i < n / 2; i++) {
    
    
            bool ok = false;
            for (int j = 0; j < 26; j++) {
    
    
                if (m[i][j] && m[n - i - 1][j]) {
    
    
                    ok = true;
                    break;
                }
            }
            if (!ok) {
    
    
                cout << "No" << endl;
                goto end;
            }
        }
        cout << "Yes" << endl;
    end:;
    }
    // fclose(stdin);
    // fclose(stdout);
    return 0;
}

I.对称之美

题目

给出一个字符串,求最长非回文子字符串的长度

思路

特判字符串 s s s 是否全为同一字符,若是,输出0;否则判断是否为回文串,是则输出 ∣ s ∣ − 1 |s|-1 s1,否则输出 ∣ s ∣ |s| s

Accepted code

/*
 * @Autor: CofDoria
 * @Date: 2021-01-10 19:20:31
 * @LastEditTime: 2021-01-10 19:28:37
 */
#include <bits/stdc++.h>
using namespace std;

#define db double
#define ll long long
#define inf 0x3f3f3f3f
#define s(a, n) memset(a, n, sizeof(a))
#define debug(a) cout << '#' << a << '#' << endl
#define rep(l, a, b) for (register ll l = a; l < b; ++l)
#define per(l, a, b) for (register ll l = a; l >= b; --l)
#define _ios ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
#define _forit(i, c) \
    for (__typeof__((c).begin()) i = (c).begin(); i != (c).end(); ++i)

bool fi = true;
const unsigned long long MOD = 1e9 + 7;

inline ll gcd(ll a, ll b) {
    
     return (b == 0 ? a : gcd(b, a % b)); }

map<char, int> s;

int main() {
    
    
    // freopen("in.txt", "r", stdin);
    // freopen("out.txt", "w", stdout);
    string a, b;
    cin >> a;
    b = a;
    for (int i = 0; i < a.size(); i++) {
    
    
        s[a[i]]++;
    }
    reverse(a.begin(), a.end());
    // cout << a << endl << b << endl;
    if (s.size() == 1) {
    
    
        cout << 0;
        return 0;
    }
    if (a == b) {
    
    
        cout << a.size() - 1;
        return 0;
    }
    cout << a.size();
    // fclose(stdin);
    // fclose(stdout);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_46144509/article/details/112460717