2024萌新联赛2

萌新联赛补题

2024 河南萌新联赛 2


状态 + 狗运+ py 大法,目前最好的一把


I 重生之zbk要拿回属于他的一切

签到,暴力找 $chuan$ 的数量即可

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
#include <bits/stdc++.h>
using namespace std;

int main() {
    int n;
    cin >> n;
    string s;
    cin >> s;
    int pos = s.find("chuan"), cnt = 0;
    while (pos != string::npos) {
        cnt++;
        pos = s.find("chuan", pos + 1);
    }
    cout << cnt << endl;
    return 0;
}

F 水灵灵的小学弟

观察题目,发现博弈双方名称相同,不管谁赢都一样,直接输出即可

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
#include <bits/stdc++.h>
using namespace std;
int main(){
    int t;
    cin>>t;
    while(t--){
        int a,b;
        cin>>a>>b;
        cout<<"DHY\n";
    }
}

A 国际旅行 I

认真读题可得知,恒为联通图,排序所有国家即可。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
#include <bits/stdc++.h>
using namespace std;
const int N = 1e6+10;

int n,m,q,k;
vector<int>a(N);
map<int,int>vis;

int main(){
    cin>>n>>m>>q;
    for(int i=1;i<=n;i++)cin>>a[i];
    for(int i=1;i<=m;i++){
        int u,v;
        cin>>u>>v;
    }
    sort(a.begin()+1,a.begin()+1+n);
    while(q--){
        cin>>k;
        cout<<a[k]<<endl;
    }
}

J 这是签到

矩阵计算板

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#include <bits/stdc++.h>
using namespace std;

int n,m;
int a[6][6];

int cal(int n, int a[6][6]) {
    if (n == 1)
        return a[0][0];
    int res = 0;
    int sub[6][6];
    for (int x = 0; x < n; x++) {
        int subi = 0;
        for (int i = 1; i < n; i++) {
            int subj = 0;
            for (int j = 0; j < n; j++) {
                if (j == x) continue;
                sub[subi][subj] = a[i][j];
                subj++;
            }
            subi++;
        }
        res += (x % 2 == 0 ? 1 : -1) * a[0][x] * cal(n - 1, sub);
    }
    return res;
}

int main() {
    cin >> n >> m;
    for (int i = 0; i < n; i++)
        for (int j = 0; j < m; j++)
            cin >> a[i][j];
    int ans = INT_MAX;
    int u=min(n,m);
    for(int i=1;i<=u;i++){
        ans=min(ans,cal(i,a));
    }
    cout << ans << endl;
    return 0;
}

H 狼狼的备忘录

STL 大法好

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#include <bits/stdc++.h>
using namespace std;

int n, cnt, m;
string s;
map<string, vector<string>> note;
map<string, map<string, int>> vis;
set<string> peo;

void erase(string &a, string &b) {
    if (a == b) {
        b = "";
        return;
    }
    if (a.size() > b.size() && a.substr(a.size() - b.size()) == b) {
        b = "";
    }
}

int main() {
    cin >> n;
    for (int i = 1; i <= n; i++) {
        cin >> s >> cnt;
        peo.insert(s);
        for (int j = 1; j <= cnt; j++) {
            string t;
            cin >> t;
            if (!vis[s][t]) note[s].push_back(t);
            vis[s][t]++;
        }
    }
    for (auto x : peo) {
        int m = note[x].size();
        for (int i = 0; i < m; i++) {
            for (int j = i + 1; j < m; j++) {
                erase(note[x][i], note[x][j]);
                erase(note[x][j], note[x][i]);
            }
        }
        sort(note[x].begin(), note[x].end());
        note[x].erase(remove(note[x].begin(), note[x].end(), ""), note[x].end());
    }
    cout << peo.size() << endl;
    for (auto x : peo) {
        cout << x << " " << note[x].size();
        for (auto s : note[x]) {
            cout << " " << s;
        }
        cout << endl;
    }

    return 0;
}

D A*BBBB

高精度 根据题意可知 是同一个结果往前移 $b.size()$ 次相加 赛时笨比没调出来 python 引入 demical 库过的

赛时代码

1
2
3
4
5
6
from decimal import *
import sys
t=int(input())
for i in range(t):
    setcontext(Context(prec=2000000, Emax=2000000, Emin=0)) 
    print((Decimal(sys.stdin.readline())*Decimal(sys.stdin.readline())))

正解

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#include <bits/stdc++.h>
using namespace std;
const int N = 1e7+10;
typedef long long ll;

int a[N],sum[N],ans[N<<1];
string A,B;

void solve(){
    cin>>A>>B;
    int la=A.length(),lb=B.length(),b=B[0]-'0';
    ll last=0;
    a[la+1]=0;
    for(int i=1;i<=la;i++){
        a[i]=(A[la-i]-'0')*b+last;
        last=a[i]/10;
        a[i]*=10;
        sum[i]=sum[i-1]+a[i];
    }
    sum[la+1]=sum[la]+last;
    last=0;
    for(int i=1;i<=la+lb;i++){
        int l=min(i,la+1),r=max(0,i-lb);
        ans[i]=sum[l]-sum[r]+last;
        last=ans[i]/10;
        ans[i]%=10;
    }
    bool flag=0;
    for(int i=la+lb;i>=1;--i) {
        if(!ans[i]) {
            if(flag)  printf("%d",ans[i]);
        } else {
            flag=1;
            printf("%d",ans[i]);
        }
    }
    if(!flag)  printf("0");
    printf("\n");
}

int main(){
    int t;
    cin>>t;
    while(t--)solve();
    return 0;
}

E “好"字符

观察得到 $a$,$b$ 同一字符所处位置相邻差值构成的一个循环同构如果相同,就符合题意
那么就对 26 个字符各跑一次 找到位置 存入字符串 找到该串的最小表示 比较即可
需要注意将原 $a$,$b$ 再复制本身一遍 因为这样才能保证找的最小表示没有缺少

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
#include <bits/stdc++.h>
using namespace std;

int kmp(int nxt[], string a) {
    int n = a.size();
    nxt[0] = 0;
    int j = 0;
    for (int i = 1; i < n; i++) {
        while (j && a[i] != a[j])
            j = nxt[j - 1];
        if (a[i] == a[j])
            j++;
        nxt[i] = j;
    }
    return n - nxt[n - 1];
}

string getmin(string s, int n) {
    s = s + s;
    int i = 0, j = 1;
    while (j < n) {
        int k = 0;
        while (k < n && s[i + k] == s[j + k]) ++k;
        if (s[i + k] > s[j + k]) i += k + 1;
        else j += k + 1;
        if (i == j) j++;
        if (i > j) swap(i, j);
    }
    string t = s.substr(i, n);
    return t;
}

int main() {
    int n;
    string a, b;
    cin >> n >> a >> b;
    a = a + a;
    b = b + b;
    map<char, vector<int>> va, vb;
    map<char, string> sa, sb;
    for (int i = 0; i < n * 2; i++) {
        va[a[i]].push_back(i);
        vb[b[i]].push_back(i);
    }
    int cnt = 0, nxt[2000010];
    for (char x = 'a'; x <= 'z'; x++) {
        if (va[x].size() != vb[x].size() || va[x].size() == 0 || vb[x].size() == 0) continue;
        for (int i = 1; i < va[x].size(); i++) {
            sa[x] += to_string(va[x][i] - va[x][i - 1]);
        }
        for (int i = 1; i < vb[x].size(); i++) {
            sb[x] += to_string(vb[x][i] - vb[x][i - 1]);
        }
        if (getmin(sa[x], kmp(nxt, sa[x])) == getmin(sb[x], kmp(nxt, sb[x]))) cnt++;
    }
    cout << cnt << endl;
    return 0;
}

C 小 $w$ 和大 $W$ 的对决

sg 暴力打表 发现 8 个为一个循环 最后两个交换位置

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
#include <bits/stdc++.h>
using namespace std;

int calc(int x){
    if(x%8==0)return x-1;
    if(x%8==7)return x+1;
    else return x;
}

int ans;

int main(){
    int n,x;
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>x;
        ans^=calc(x);   
    }
    if(ans==0)cout<<"W win\n";
    else cout<<"w win\n";
}

G $lxy$ 的通风报信

因为数据不大,直接 bfs 跑每个点对其他点的距离,再求最小生成树即可

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
#include <bits/stdc++.h>
using namespace std;
const int N = 1010;

struct Node{
    int x,y,id;
}b[N];

int n,m,ans,dx[4]={1,0,-1,0},dy[4]={0,1,0,-1},tot,dis[N][N],a[N][N];
bool vis[N];
deque<Node>q;

void bfs(int id){
    q.clear();
    q.push_back(Node{b[id].x,b[id].y,0});
    dis[b[id].x][b[id].y]=0;
    while(!q.empty()){
        Node now=q.front();
        q.pop_front();
        for(int i=0;i<4;i++){
            int x=now.x+dx[i],y=now.y+dy[i];
            if(x<1||y<1||x>n||y>m||a[x][y]==-1)continue;
            if(dis[x][y]>now.id+1){
                dis[x][y]=now.id+1;
                q.push_back(Node{x,y,dis[x][y]});
            }
        }
    }
}

void solve(){
    cin>>n>>m;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            dis[i][j]=1e9;
            char x;
            cin>>x;
            if(x=='.')a[i][j]=0;
            else if(x=='#')a[i][j]=-1;
            else {
                a[i][j]=++tot;
                b[tot]=Node{i,j,tot};   
            }
        }
    }
    dis[b[1].x][b[1].y]=0;
    for(int i=1;i<=tot;i++){
        int mi=1e9,id=0;
        for(int j=1;j<=tot;++j){
            if(vis[j])continue;
            if(mi>dis[b[j].x][b[j].y])mi=dis[b[j].x][b[j].y],id=j;
        }
        if(!id){
            puts("No");
            return;
        }
        vis[id]=1;
        ans+=mi;
        if(i!=tot)bfs(id);
    }
    cout<<ans<<endl;
}

int main(){
    int t=1;
//     cin>>t;
    while(t--)solve();
    return 0;
}
Licensed under CC BY-NC-SA 4.0
发表了95篇文章 · 总计15万2千字
永远相信美好的事情即将发生。
使用 Hugo 构建
主题 StackJimmy 设计