2018年第十届ACM四川省省赛题解(10 / 11)
Posted 繁凡さん
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2018年第十届ACM四川省省赛题解(10 / 11)相关的知识,希望对你有一定的参考价值。
整理的算法模板合集: ACM模板
实际上是一个全新的精炼模板整合计划
2018ACM四川省省赛
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. 数列求值