整理的算法模板合集: 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

目录

  • 2018ACM四川省省赛
  • A. Angel Beats
  • B. Beyond the Boundry
  • C. Clannad
  • D. Darling in the Franxx
  • E. Ever17
  • F. Fullmetal Alchemist
  • G. Grisaia
  • H. Harmony
  • I. Island
  • J. JoJo’s Bizarre Adventure
  • K. Kanon

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()
{int t;scanf("%d",&t);while(t--){solve();}return 0;
}

E. Ever17

Problem

Solution

模拟即可,注意 01/01/01 和 01/01/01 是同一天,所以要输出 January 1, 2001,因为是同一天。

Code

#include <bits/stdc++.h>
using namespace std;string s[13] = {"","January","February","March","April","May","June","July","August","September","October","November","December"};int day[13] = {0,31,28,31,30,31,30,31,31,30,31,30,31};
int addone(int y)
{if(y % 4 == 0) return 1;return 0;
}bool check1(int a,int b,int c)
{if(a > 12 || a < 1) return 0;if(b < 1 || b > day[a] + (a == 2 ? addone(c) : 0)) return 0;return 1;
}int calc(vector<int> a, vector<int> b)
{if(a > b) swap(a,b);int cnt = 0;while(a != b){a[2]++;if(a[2] > day[a[1]] + (a[1] == 2 ? addone(a[0]) : 0) ) a[2] = 1,a[1]++;if(a[1] == 13) a[1] = 1,a[0]++;cnt++;}return cnt;
}int main()
{int t;scanf("%d",&t);while(t--){int a,b,c;scanf("%d/%d/%d",&a,&b,&c);vector<int> x,y;if(check1(a,b,c)) x.push_back(c),x.push_back(a),x.push_back(b);if(check1(b,c,a)) y.push_back(a),y.push_back(b),y.push_back(c);if(x.size() && y.size() && x != y){int cnt = calc(x,y);printf("%d\n",cnt);continue;}if(x.size()){cout<<s[x[1]];printf(" %d, 20%02d\n",x[2],x[0]);continue;}if(y.size()){cout<<s[y[1]];printf(" %d, 20%02d\n",y[2],y[0]);continue;}} return 0;
}

F. Fullmetal Alchemist

Problem

Solution

考虑 O(n2)O(n^2)O(n2) 枚举子区间,枚举的同时维护对顶堆,复杂度 O(T∗n2∗logn)O(T*n^2*logn)O(T∗n2∗logn)

Code

#include <bits/stdc++.h>
using namespace std;
const int maxn = 2005;
using ll = long long;
int a[maxn];
ll sum[maxn];
ll ans[maxn];int main()
{int t;scanf("%d",&t);while(t--){int n;memset(ans,0,sizeof(ans));scanf("%d",&n);for(int i = 1;i <= n;++i){scanf("%d",&a[i]);sum[i] = sum[i-1]+a[i]; }for(int i = 1;i <= n;++i){priority_queue<int,vector<int>,greater<int>> mx;priority_queue<int,vector<int>,less<int>> mi;bool now = 1;ll add = 0;for(int j = i;j <= n;++j){if(now){if(mi.empty())mi.push(a[j]),add+=a[j];else{int tmp = mx.top();if(a[j] > tmp){mx.pop();mx.push(a[j]);mi.push(tmp);add += tmp;}else {mi.push(a[j]);add += a[j];}}}else{int tmp = mi.top();if(a[j] < tmp){mi.pop();mi.push(a[j]);mx.push(tmp);add -= tmp-a[j];}else {mx.push(a[j]);}ans[(j-i+1)/2] = max(ans[(j-i+1)/2],sum[j]-sum[i-1]-add-add);// cout<<i<<' '<<j<<' '<<add<<' '<<sum[j]-sum[i-1]-add-add<<endl;}now = !now;}}for(int i = 1;i <= n/2;++i)printf("%lld%c",ans[i],(i==n/2?'\n':' '));}return 0;
}

G. Grisaia

Problem

计算:

ans=∑i=1n∑j=1i(nmod(i×j))ans =\sum^n_{i=1}\sum^i_{j=1} (n\ mod (i \times j))ans=i=1∑n​j=1∑i​(n mod(i×j))

其中 t≤5,n≤1011t\le 5, n\le 10^{11}t≤5,n≤1011

Solution

使用模的展开式将上述和式展开后,显然枚举 k=i×jk=i\times jk=i×j,由于 n≤1011n\le10^{11}n≤1011,杜教筛即可。

筛出:

f(x)=x×∑i∣k1g(x)=x×μ(x)f(x)=x\times \sum\limits_{i|k} 1\\g(x)=x \times \mu(x)f(x)=x×i∣k∑​1g(x)=x×μ(x)

然后整除分块即可。

详解见这里:https://blog.csdn.net/weixin_45697774/article/details/117172503

附训练赛时草稿纸一份:


这里是杜教筛筛出来 g(x)=x×μ(x)g(x)=x\times \mu(x)g(x)=x×μ(x):

注意 n≤1011n\le10^{11}n≤1011,中间多处会爆 long long,强转成 __int128 即可。

(因为这个wa了8发hhh,五颜六色的)

Code

#include <bits/stdc++.h>using namespace std;
#define int long long
#define ll __int128
const int N = 31644346;int n, m;
int mu[N];
int primes[N], cnt;
int d[N];
int num[N];
unordered_map<int, ll> sum_mui;
unordered_map<int, ll> sum_dk;
bool vis[N];
int sum[N];inline ll read()
{register ll x = 0,f = 1;char c = getchar();while(c < '0' || c > '9') {if(c == '-') f = -1;c = getchar();}while(c >= '0' && c <= '9') x = x * 10 + c-48,c = getchar();return x * f;
}inline void print(ll x)
{if(x < 10){putchar(x + 48);return;}print(x / 10), print(x % 10);
}void init(int n)
{vis[0] = vis[1] = 1;mu[1] = d[1] = 1;for(int i = 2; i <= n; ++ i) {if(vis[i] == 0) {primes[ ++ cnt] = i;mu[i] = -1;d[i] = 2 * i;num[i] = 1;}for(int j = 1; j <= cnt && i * primes[j] <= n; ++ j) {vis[i * primes[j]] = 1;if(i % primes[j] == 0) {mu[i * primes[j]] = 0;num[i * primes[j]] = num[i] + 1;d[i * primes[j]] = (ll)d[i] / num[i * primes[j]] * (num[i * primes[j]] + 1) * primes[j];break;}mu[i * primes[j]] -= mu[i];num[i * primes[j]] = 1;d[i * primes[j]] = d[i] * d[primes[j]];}}for(int i = 1; i <= n; ++ i) {sum[i] = sum[i - 1] + mu[i] * i;d[i] = d[i - 1] + d[i];}
}inline ll get_sum_mui(int x)
{if(x <= N - 7) return sum[x];if(sum_mui.find(x) != sum_mui.end()) return sum_mui[x];ll ans = 1;for(ll l = 2, r; l <= x; l = r + 1) {r = x / (x / l);ans -= (ll)(r - l + 1) * (l + r) / 2 * get_sum_mui(x / l);}   return sum_mui[x] = ans;
}inline ll get_sum_dk(ll x)
{if(x <= N - 7) return d[x];if(sum_dk.find(x) != sum_dk.end()) return sum_dk[x];ll ans = x * (x + 1) / 2;for(ll l = 2, r; l <= x; l = r + 1) {r = x / (x / l);ans -= (ll)(get_sum_mui(r) - get_sum_mui(l - 1)) * get_sum_dk(x / l);}return sum_dk[x] = ans;
}ll cal(ll x)
{ll limit = sqrt(x + 0.99);ll more = limit * (limit + 1) * (2 * limit + 1) / 6;return (get_sum_dk(x) + more) / 2;
}void solve()
{ll ans = (ll)n * n * (n + 1) / 2;for(ll l = 1, r; l <= n; l = r + 1) {r = n / (n / l);//cout << "ok" << cal(r) - cal(l - 1) * (n / l) << endl;ans -= (ll)(cal(r) - cal(l - 1)) * (n / l);}print(ans);puts("");
}signed main()
{int t;init(N - 7);t = read();while(t -- ) {n = read();solve();}return 0;
}

H. Harmony

Problem

给你 a,ba,ba,b,你自己选一个 ccc,使得 a+b+gcd⁡(a,b,c)a + b + \gcd(a, b, c)a+b+gcd(a,b,c) 最大,输出这个最大的 a+b+gcd⁡(a,b,c)a + b + \gcd(a, b, c)a+b+gcd(a,b,c)

Solution

显然 c=gcd⁡(a,b)c=\gcd(a,b)c=gcd(a,b) 时,a+b+gcd⁡(a,b,c)a + b + \gcd(a, b, c)a+b+gcd(a,b,c) 最大

Code

#include <bits/stdc++.h>
using namespace std;int main()
{int t;scanf("%d",&t);while(t--){int a,b;scanf("%d%d",&a,&b);printf("%d\n",a + b + __gcd(a,b));} return 0;
}

I. Island

Problem

Solution

根据题意直接 dfs 即可

Code

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const int maxn = 2e5+5;ll dp[maxn];
ll sum = 0;
ll val[maxn];
vector<int> edge[maxn];
ll ans;void dfs(int now,int pre)
{dp[now] = val[now];ll mx = 0;for(auto &x:edge[now]){if(x==pre)continue;dfs(x,now);dp[now] += dp[x];mx = max(mx,dp[x]);}mx = max(mx,sum-dp[now]);ans = min(ans,mx);
}void solve()
{int n;scanf("%d",&n);for(int i = 1;i <= n;++i)edge[i].clear();sum = 0;for(int i = 1;i <= n;++i)scanf("%lld",&val[i]),sum += val[i];for(int i = 1,a,b;i < n;++i){scanf("%d%d",&a,&b);edge[a].push_back(b);edge[b].push_back(a);}ans = 1e18;dfs(1,0);printf("%lld\n",ans);
}int main()
{int t;scanf("%d",&t);while(t--){solve();}return 0;
}

J. JoJo’s Bizarre Adventure

Problem

Translation

jojo 有一个长度为 nnn 的 aaa 数组,其中保证 a0=0a_0=0a0​=0,且 0=a1≤a2≤⋅⋅⋅≤an0 = a_1 ≤ a_2 ≤ · · · ≤ a_n0=a1​≤a2​≤⋅⋅⋅≤an​,jojo 构造出了一个多重集:Smulti={ai+aj∣1≤i<j≤n}S_{multi} = \{a_i+a_j |1 ≤ i < j ≤ n\}Smulti​={ai​+aj​∣1≤i<j≤n},其中保证 SmultiS_{multi}Smulti​ 非严格单调递增。

Dio 想要最少需要知道多少个 SmultiS_{multi}Smulti​ 里的元素,就可以推断出原序列 aaa。

T≤10,n≤500,Smulti.size=n(n−1)2T\le 10,n\le 500,S_{multi}.size=\cfrac{n(n-1)}{2}T≤10,n≤500,Smulti​.size=2n(n−1)​

Solution

题太难理解了…
读懂题之后直接模拟即可…
注意特判…

Code

#include <bits/stdc++.h>
using namespace std;const int N = 3e5 + 10;
int a[N];
unordered_map<int,int> mp;int main()
{int t;scanf("%d",&t);while(t--){mp.clear();int n;scanf("%d",&n);vector<int> res;int m = n * (n-1) / 2;for(int i = 1;i <= m;++i){scanf("%d",&a[i]);}if(n == 1){puts("0");continue;}if(n == 2){puts("1");continue;}if(n == 3){puts("2");continue;}res.push_back(0);res.push_back(a[1]);res.push_back(a[2]);// mp[a[1]] = 0, mp[a[2]] = 1;mp[a[1] + a[2]] = 1;int cnt = 2;for(int i = 3;i <= m;++i){if(mp[a[i]]) {mp[a[i]]--;continue;}for(int j = 1;j < res.size();++j) {mp[a[i] + res[j]]++;}res.push_back(a[i]);if((int)res.size() == n){cnt = i;break;}}printf("%d\n",cnt);}return 0;
}

K. Kanon

Problem

Solution

Code

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

  1. “科林明伦杯”哈尔滨理工大学第十届程序设计竞赛(同步赛) 题解

    "科林明伦杯"哈尔滨理工大学第十届程序设计竞赛(同步赛) 题解 萌新又来写题解啦 原题链接 B 减成一 题意:存在n个数,每次操作可以任选一个区间使得区间内的所有数字减一.问最少多 ...

  2. 第十届蓝桥杯省赛题解+代码

    文章目录 组队(5分)(暴力) 年号字符(5分) 题解 AC 数列求值(10分)(递推) 题解 AC 数的分解(10分)(暴力) 题解 AC 迷宫(15分)(BFS) 题解 AC代码 特别数的和(15 ...

  3. 四川高中计算机大赛官网,2018年(第十届)四川省大学生程序设计竞赛

    2018年(第十届) 四川省大学生程序设计竞赛 2018年6月1-3日,由四川省教育厅主办,西南科技大学承办的第十届四川省大学生程序设计竞赛在西南科技大学举行.本次参赛队伍以四川省内高校队伍为主,同时 ...

  4. 第三十届ACM/ICPC 世界总决赛题目解析

    第三十届ACM/ICPC 世界总决赛题目解析 斯坦福大学 王颖

  5. 计算机操作技能竞赛系列方案,2018年第十届学生技能展示计算机专业活动方案...

    清丰县职业技术学校 2018年第十届学生技能展示计算机专业活动方案 一.指导思想 为培养学生健康的审美情趣.良好的专业艺术素养,展现学生良好的精神风貌,推进专业技能训练.营造积极向上.健康文明的校园文 ...

  6. 2019年第十届蓝桥杯 - 省赛 - C/C++研究生组 - G. 扫地机器人

    2019年第十届蓝桥杯 - 省赛 - C/C++研究生组 - G. 扫地机器人 Ideas 首先我们根据数学常识可以知道,当每个机器人清扫的范围差不多时,最好都是 N / K,花的时间应该是最少的. ...

  7. 蓝桥杯:试题 历届真题 修改数组【第十届】【省赛】【研究生组】Java实现

    代码实现 方法一: package com.jl;import java.util.Scanner;/*** 历届真题 修改数组[第十届][省赛][研究生组]* @author jinlei**/ p ...

  8. java蓝桥杯省赛第十届_2019年第十届蓝桥杯省赛-迷宫(BFS/Excel大法)

    这题用dfs搜不出来,需要使用bfs并记录路径,设置好方向顺序跑就ok 然而毕竟是暴力杯,我们的原则是代码能省就省(懒癌晚期 于是乎网上便出现了形形色色的题解,笔者综合了各路大神神乎其技的思想,总结出 ...

  9. java迷宫类编程题_第十届蓝桥杯省赛java类B组 试题 E:迷宫 (动态规划之回溯法)...

    问题描述 试题 E: 迷宫 [问题描述] 下图给出了一个迷宫的平面图,其中标记为 1 的为障碍,标记为 0 的为可 以通行的地方. 010000 000100 001001 110000 迷宫的入口为 ...

最新文章

  1. java 物理地址_java中的==与equals的区别是什么,什么是物理地址?
  2. 解决IDEA使用lombok注解无效,@Data不生效问题
  3. SUSTech-Application
  4. Git忽略规则.gitignore梳理
  5. Unity游戏开发之C#快速入门
  6. abp mysql .net core_ABP Asp.Net Core 集成 MySql 数据库
  7. java hibernate 分页取数_java – Hibernate分页机制
  8. Oracle笔记 五、创建表、约束、视图、索引、序列、同义词、表空间
  9. Stackelberg博弈
  10. Android之NDK开发入门
  11. 【Flutter 问题系列第 7 篇】TextField 去掉下划线
  12. 后台返回图片报404的问题解决
  13. 三维重建入门学习————建模软件Blender入门篇
  14. 无线充电安全性如何?最安全的无线充电宝盘点
  15. 一个在线显示doc文本的实例
  16. 基于springboot项目中使用docker-compose+es+kibana+logstash+mysql 提高数据查询效率
  17. HDU 6217 BBP Formula (数学)
  18. 经验分享:Python3离线安装及库更新
  19. LiveUpdate Adminstrator配置
  20. 快车移动端SDK使用说明

热门文章

  1. 干货 | 非常全面的谱聚类算法原理总结
  2. 图像超分辨率网络:RCAN
  3. 深度学习七个实用技巧
  4. 基于OpenCV与tensorflow实现实时手势识别
  5. 干货 | 使用FFT变换自动去除图像中严重的网纹
  6. 使用OpenCV进行对象检测
  7. 关于WeX5的初步学习
  8. Elasticsearch创建雇员目录
  9. 操作临时表+事务级别临时表操作+会话级别临时表操作
  10. 第五章 业务架构,5.3 千亿访问量下的开放平台技术揭秘(作者:风胜)