2018年第十届ACM四川省省赛题解(10 / 11)

Posted 繁凡さん

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2018年第十届ACM四川省省赛题解(10 / 11)相关的知识,希望对你有一定的参考价值。

整理的算法模板合集: ACM模板

点我看算法全家桶系列!!!

实际上是一个全新的精炼模板整合计划


2018ACM四川省省赛

题目链接:https://www.oj.swust.edu.cn/problem/search?word=The%202018%20Sichuan%20Provincial%20Collegiate%20Programming%20Contest&scope=source
在这里插入图片描述

在这里插入图片描述
5小时训练赛过9题

然后上周刚刚结束的2021年四川省赛同样9题拿金了,好耶,差两名拿季军奖杯Orz

A. Angel Beats

Problem

Solution

Code

#include <bits/stdc++.h>
using namespace std;
 
const int maxn = 1e4+2;
bitset<maxn>dp[maxn],sum[maxn],ans;
 
void solve()
{
    int n,m;
    scanf("%d%d",&n,&m);
    for(int i = 1;i <= n+1;++i){
        sum[i].reset();
        dp[i].reset();
    }
    for(int i = n;i >= 1;--i){
        dp[i].set(i);
        for(int j = i+i;j <= n;j += i){
            dp[i] ^= dp[j];
        }
        sum[i] = dp[i]^sum[i+1];
    }
    ans.reset();
    for(int i = 1,a,b;i <= m;++i){
        scanf("%d%d",&a,&b);
        ans ^= sum[a]^sum[b+1];
        printf("%d\\n",ans.count());
    }
}
 
int main()
{
    int t;
    scanf("%d",&t);
    while(t--){
        solve();
    }
}

B. Beyond the Boundry

Problem
在这里插入图片描述

Solution

暴力即可。

Code

#include <bits/stdc++.h>
using namespace std;
 
string ss[4] = {"Kanbara Akihito", "Kuriyama Mirai","Nase Hiroomi","Nase Mitsuki"};
 
bool check(string a, string b)
{
    int i = 0;
    int j = 0;
    while(i < (int)a.size() && j < (int)b.size()){
        if(b[j] == a[i]){
            i++;
        }
        j++;
    }
    return i == (int)a.size();
 
}
 
int main()
{   
    int t;
    scanf("%d",&t);
    while(t--){
        string s;
        cin>>s;
        vector<string> tmp;
        for(int i = 0;i < 4;++i){
            if(check(s,ss[i])) tmp.push_back(ss[i]);
        }
        printf("%d\\n",(int)tmp.size());
        for(auto it : tmp) cout << it << endl;
    }
 
 
    return 0;
}

C. Clannad

Problem
在这里插入图片描述

Solution

AC自动机上DP即可。

Code

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const int mod = 1e9+7;
const int maxn = 1e5+5;
 
struct ACAM
{
    int tree[maxn][26],fail[maxn],last[maxn],tot,end[maxn],len[maxn];
    ll dp[maxn];
    void init()
    {
        memset(dp,0,sizeof(dp));
        dp[0] = 1;
        tot = 0;
        memset(tree,0,sizeof(tree));
        memset(fail,0,sizeof(fail));
        memset(last,0,sizeof(last));
        memset(end,0,sizeof(end));
        memset(len,0,sizeof(len));
    }
    void Insert(const char *s){
        int root = 0;
        int l = 0;
        for(int i = 0;s[i];++i){
            int p = s[i]-'a';
            l++;
            if(!tree[root][p]){
                tree[root][p] = ++tot;
                len[tot] = l;
            }
            root = tree[root][p];
        }
        end[root] = 1;
    }
    void get_fail(){
        queue<int> q;
        for(int i = 0;i < 26;++i){
            if(tree[0][i])
            q.push(tree[0][i]); 
        }
        while(!q.empty()){
            int now = q.front();
            q.pop();
            last[now] = end[fail[now]]?fail[now]:last[fail[now]];
            for(int i = 0;i < 26;++i){
                if(tree[now][i]){
                    q.push(tree[now][i]);
                    fail[tree[now][i]] = tree[fail[now]][i];
                }
                else tree[now][i] = tree[fail[now]][i];
            }
        }
    }
    void solve(const char*s,int n){
        int root = 0;
        for(int i = 1;i <= n;++i){
            root = tree[root][s[i]-'a'];
            int tmp = root;
            if(end[root]){
                dp[i] += dp[i-len[root]];
                dp[i] %= mod;
            }
            tmp = last[tmp];
            while(tmp){
                dp[i] += dp[i-len[tmp]];
                dp[i] %= mod;
                tmp = last[tmp];
            }
            printf("%lld%c",dp[i],i==n?'\\n':' ');
        }
    }
}ac;
char s[maxn],t[maxn];
 
void solve()
{
    ac.init();
    int n,q;
    scanf("%d%d",&n,&q);
    scanf("%s",s+1);
    for(int i = 1;i <= q;++i){
        scanf("%s",t);
        ac.Insert(t);
    }
    ac.get_fail();
    ac.solve(s,n);
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--){  
        solve();
    }
}
 
// 9 5
// zzbzzbcbb
// zz
// z
// zb
// cb
// b

D. Darling in the Franxx

Problem

在这里插入图片描述
Solution

首先以 1 为根进行 dfs ,记录一下祖先信息,dfs序。对于任意两个点若他们不是祖先关系则只有当他们的子树上的点为根时才能满足祖先关系。若是祖先关系,则他们路径上的点及其所有子节点都不能作为根。因为一个点的子树上的点的dfs序都是连续的所以对子树上的点打标记用差分即可。

Code

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5+5;
const int LGS = 18;
vector<int> edge[maxn];
int dfn[maxn],rnk[maxn],dfn_clock;
int l[maxn],r[maxn];
int son[maxn],dep[maxn];
int fa[maxn][20];
int val[maxn];
 
void dfs(int now,int pre)
{
    l[now] = ++dfn_clock;
    dep[now] = dep[pre]+1;
    fa[now][0] = pre;
    for(int i = 1;i <= LGS;++i){
        fa[now][i] = fa[fa[now][i-1]][i-1];
    }
    for(auto &x:edge[now]){
        if(x==pre)continue;
        dfs(x,now);
    }
    r[now] = dfn_clock;
}
int lca(int x,int y)
{
    if(dep[x] < dep[y])swap(x,y);
    for(int i = LGS;i >= 0;--i){
        if(dep[fa[x][i]] >= y)x = fa[x][i];
    }
    for(int i = LGS;i >= 0;--i){
        if(fa[x][i]!=fa[y][i]){
            x = fa[x][i];
            y = fa[y][i];
        }
    }
    if(x!=y)return fa[x][0];
    return x;
}
 
void init()
{
    dfn_clock = 0;
    memset(son,0,sizeof(son));
    memset(val,0,sizeof(val));
}
 
void solve()
{
    int n,m;
    scanf("%d%d",&n,&m);
    for(int i = 1;i <= n;++i)edge[i].clear();
    init();
    for(int i = 1,a,b;i < n;++i){
        scanf("%d%d",&a,&b);
        edge[a].push_back(b);
        edge[b].push_back(a);
    }
    dfs(1,0);
    for(int i = 1,a,b;i <= m;++i){
        scanf("%d%d",&a,&b);
        int g = lca(a,b);
        if(dep[a] > dep[b])swap(a,b);
        if(g==a){
            int x = b;
            for(int i = LGS;i >= 0;--i){
                if(dep[fa[x][i]]>dep[g])x = fa[x][i];
            }
            val[1]++;
            val[l[x]]--,val[r[x]+1]++;
            val[l[b]]++,val[r[b]+1]--;
        }
        else{
            val[l[a]]++,val[r[a]+1]--;
            val[l[b]]++,val[r[b]+1]--;
        }
    }
    int ans = 0;
    for(int i = 1;i <= n;++i){
        val[i] += val[i-1];
        ans += val[i]==m;
    }
    printf("%d\\n",ans);
}
int main()
第十届四川省ACM赛前总结

2019年第十届蓝桥杯 - 省赛 - Java研究生组 - A. 立方和

2019年第十届蓝桥杯 - 省赛 - C/C++大学B组 - C. 数列求值

[蓝桥杯][2019年第十届省赛真题] 糖果 (IDA*解决重复覆盖问题)

2019年第十届C/C++ A组蓝桥杯省赛第四题:迷宫

2019年第十届C/C++ A组蓝桥杯省赛第四题:迷宫