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

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

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


VP了一下,体验不是太好,区分度不是很好,简单题太简单,难题看着就不想写…没什么意思

比赛地址:

https://ac.nowcoder.com/acm/contest/15600

%VP地址(密码 swpuacm):
%[https://ac.nowcoder.com/acm/contest/16646#description]https://ac.nowcoder.com/acm/contest/16646#description)

目录

  • 第十一届山东省大学生程序设计竞赛(9 / 13)
    • B. Build Roads
    • C. Cat Virus
    • D. Dyson Box
    • F. Birthday Cake
    • G. Grade Point Average
    • H. Adventurer's Guild
    • J. Tuition Agent
    • L. Construction of 5G Base Stations
    • M. Matrix Problem

第十一届山东省大学生程序设计竞赛(9 / 13)

B. Build Roads

Problem

给定一个 nnn 个点的无向完全图,iii 和 jjj 之前的边权是 gcd⁡(ai,aj)\gcd(a_i,a_j)gcd(ai​,aj​) ,保证数组 a 随机,求 MST。

Solution

边权为 gcd⁡(ai,aj)\gcd(a_i, a_j)gcd(ai​,aj​),显然如果存在一个点 axa_xax​ 是素数,则从该点向所有的点连边,这样连接的 n−1n-1n−1条边的权值都是1,答案就是 n−1n-1n−1 。

若 L=RL=RL=R,则 R+L+1=1R+L+1=1R+L+1=1,模1之后得到的显然都是0,也就是说 n2n^2n2 条边的权值都是 LLL,答案显然就是 L×(n−1)L\times (n-1)L×(n−1)。

然后因为 nnn 比较大,n≤105n\le 10^5n≤105,所以我们考虑分情况讨论。

若 nnn 比较小,可以直接暴力 O(n2)O(n^2)O(n2) 连边然后求最小生成树即可。

若 nnn 较大,若 R−L+1R-L+1R−L+1 较大,则根据素数分布,int范围内的素数间距大概就是几百左右,这样 L∼L+(R−L+1)L\sim L+(R-L+1)L∼L+(R−L+1) 中一定会有素数,也就是说一定会出现一个 aiis primea_i\ \text{is\ prime}ai​ is prime,答案显然就是上面讨论的 n−1n-1n−1。

若 nnn 较大,R−L+1R-L+1R−L+1 较小,出题人可以找一个没有素数的区间 [L,R][L,R][L,R],那么答案还是 n−1n-1n−1 吗?显然仍然是,因为 nnn 较大,R−L+1R-L+1R−L+1 较小说明 a1∼ana_1\sim a_na1​∼an​ 一定会把 [L,R][L,R][L,R] 给取满了,也就是 aia_iai​ 是一堆连续的数,而相邻两个数互质,所以答案一定还是 n−1n-1n−1。

Code

#include <bits/stdc++.h>
using namespace std;
using ull = unsigned long long;
const int maxn = 2e5+5;bool prime[maxn];int n,L,R,a[maxn];
ull seed;void getprime()
{memset(prime,1,sizeof(prime));prime[1] = 1;for(int i = 2;i <= 200000;++i){if(prime[i]){for(int j = i+i;j <= 200000;j += i)prime[j] = 0;}}
}ull xorshift64()
{ull x = seed;x ^= x<<13;x ^= x>>7;x ^= x<<17;return seed=x;
}int gen()
{return xorshift64()%(R-L+1)+L;
}struct Edge
{int x,y,cost;
};void solve1()
{vector<Edge>edge;for(int i = 1;i <= n;++i){for(int j = i+1;j <= n;++j){edge.push_back({i,j,__gcd(a[i],a[j])});}}vector<int> pre(n+1);for(int i = 1;i <= n;++i)pre[i] = i;sort(edge.begin(),edge.end(),[](const Edge&a,const Edge&b)->bool{return a.cost<b.cost;});function<int(int)> Find = [&](int x)->int{return pre[x]==x?x:pre[x] = Find(pre[x]);};int ans = 0;for(auto &x:edge){int fx = Find(x.x);int fy = Find(x.y);if(fx!=fy){pre[fx] = fy;ans += x.cost;}}printf("%d\n",ans);
}int main()
{getprime();scanf("%d%d%d%llu",&n,&L,&R,&seed);for(int i = 1;i <= n;++i){a[i] = gen();}   for(int i = 1;i <= n;++i){if(prime[a[i]]){printf("%d\n",n-1);return 0;}}if(n <= 3000){solve1();}else if(L!=R){printf("%d\n",n-1);}else printf("%lld\n",1ll*R*(n-1));
}

C. Cat Virus

Problem

给定一棵树,黑白染色方案,满足一个黑点的子树都是黑点,白点任意。
你现在构造一棵树,使得它的染色方案数为 KKK。

Solution

给定方案数让我们构造出一颗满足条件的树,我们先考虑对于一颗树,我们如何计算它的方案数。

我们设 f(u)f(u)f(u) 表示染色 uuu 以及 uuu 的所有子树的方案数,显然对于 uuu 的所有子节点 vvv,其中若将 u 染成黑色结点,则方案数为1(儿子全都是黑色结点),若将 u 染成 白色,则方案数为 ∏f(v)\prod f(v)∏f(v),即:f(u)=∏(f(v)+1)+1f(u)=\prod (f(v)+1)+1f(u)=∏(f(v)+1)+1。

这里要求构造一棵染色方案数等于 kkk 的树。

对于 kkk:

若 kkk 是奇数,显然我们可以为 kkk 分配一个左右儿子 l,rl,rl,r ,我们继续往右儿子的方向往下走,这样 f(r)=k−12f(r)=\cfrac{k-1}{2}f(r)=2k−1​, f(l)=2,f(u)=f(r)×f(l)+1f(l)=2,f(u)=f(r)\times f(l)+1f(l)=2,f(u)=f(r)×f(l)+1。

若 kkk 是偶数,我们可以直接给 u 连接一个子节点,然后到下一层,方案数就变成了 k−1k-1k−1。

直接dfs即可。

Code

#include <bits/stdc++.h>using namespace std;
#define int long long
const int N = 1e5 + 7;int n, m;
int k;
int cnt;
int tot;
int u[N], v[N];void dfs(int p, int k)
{if(k == 3) {u[ ++ tot] = p;v[tot] = p + 1;return ;}if(k < 3) return ;if(k & 1) {u[ ++ tot] = p;v[tot] = p + 1;u[ ++ tot] = p;v[tot] = p + 2;dfs(p + 2, k >> 1);}else {u[ ++ tot] = p;v[tot] = p + 1;dfs(p + 1, k - 1);}
}signed main()
{scanf("%lld", &k);if(k == 2) {printf("1");return 0;}dfs(1, k);cout << tot + 1 << endl;for(int i = 1; i <= tot; ++ i) {printf("%lld %lld\n", u[i], v[i]);}return 0;
}

D. Dyson Box

Problem

二维空间里放了 nnn 个盒子,有水平往左和竖直往下两种重力,求重力作用之后形成的轮廓周长。

Solution

读完题直接模拟一下即可,一共8种情况,elif 即可。

Code

#include <bits/stdc++.h>
using namespace std;const int N = 2e5 + 10;
int U[N],L[N];int main()
{int n;scanf("%d",&n);int a = 0, b = 0;for(int i = 0;i < n;++i){int x,y;scanf("%d%d",&x,&y);x++;y++;int now = 4;int cnt = 0;if(U[x]) cnt++;U[x]++;if(U[x-1] >= U[x]) cnt++;if(U[x+1] >= U[x]) cnt++;a += now - cnt * 2;now = 4;cnt = 0;if(L[y]) cnt++;L[y]++;if(L[y-1] >= L[y]) cnt++;if(L[y+1] >= L[y]) cnt++;b += now - cnt * 2;printf("%d %d\n", a,b);}return 0;
}

F. Birthday Cake

Problem

给定 nnn 个串,求有多少对串能拼出平方串(能够表示成两个相同的字符串连接在一起的,即 AAAAAA)。

Solution

Code

#include <bits/stdc++.h>
using namespace std;
const int mod[2] = {998244353,1000000007};
const int maxn = 4e5+5;
const int sz = 233;
using ll = long long;
string a[maxn];
ll Hase[maxn][2];
ll fac[maxn][2];
map<pair<ll,ll>,int> mp;int main()
{fac[0][0] = fac[0][1] = 1;for(int i = 1;i <= 400000;++i){fac[i][0] = fac[i-1][0]*sz%mod[0];fac[i][1] = fac[i-1][1]*sz%mod[1];}ios::sync_with_stdio(false);int n;cin>>n;for(int i = 1;i <= n;++i){cin>>a[i];}sort(a+1,a+1+n,[](const string&a,const string &b)->bool{return a.size()<b.size();});ll ans = 0;for(int i = 1;i <= n;++i){ll val[2] = {0,0};for(int j = 0;j < a[i].size();++j){val[0] = val[0]*sz+a[i][j];val[0] %= mod[0];Hase[j+1][0] = val[0];val[1] = val[1]*sz+a[i][j];val[1] %= mod[1];Hase[j+1][1] = val[1];}ans += mp[make_pair(val[0],val[1])];int len = a[i].size();for(int j = 1;j <= len/2;++j){ll hs1 = Hase[j][0];ll hs2 = (Hase[len][0]-Hase[len-j][0]*fac[j][0]%mod[0]+mod[0])%mod[0];ll hs3 = Hase[j][1];ll hs4 = (Hase[len][1]-Hase[len-j][1]*fac[j][1]%mod[1]+mod[1])%mod[1];if(hs1==hs2&&hs3==hs4){ll hs5 = (Hase[len-j][0]-Hase[j][0]*fac[len-j-j][0]%mod[0]+mod[0])%mod[0];ll hs6 = (Hase[len-j][1]-Hase[j][1]*fac[len-j-j][1]%mod[1]+mod[1])%mod[1];ans += mp[make_pair(hs5,hs6)];}}mp[make_pair(val[0],val[1])]++;}cout<<ans<<endl;return 0;
}

G. Grade Point Average

输出 ∑i=1nain\cfrac{\sum_{i=1}^{n}a_i}{n}n∑i=1n​ai​​,保留小数点后 位(直接截断后面的)。

Solution

模拟除法即可。

Code

#include <bits/stdc++.h>
using namespace std;int main()
{int n,m;scanf("%d%d",&n,&m);int p = n;int q = 0;for(int i = 0;i < n;++i){int tmp;scanf("%d",&tmp);q += tmp;}string res;int gcd = __gcd(p,q);p/=gcd;q/=gcd;res+=to_string(q/p);q %= p;res.push_back('.');for(int i = 0;i < m;++i){q *= 10;res.push_back(q / p + '0');q %= p;}cout << res << endl; return 0;
}

H. Adventurer’s Guild

Problem

Yuna 的生命值是 HHH ,体力值是 SSS,有 nnn 个任务,每个任务有生命值和体力值的花费。生命值不能降到 000 或 000 以下,体力值的多余消耗会算到生命值里。求最大任务收益。

Solution

二维费用背包即可。

Code

#include <bits/stdc++.h>
using namespace std;
using ll = long long;ll dp[305][305];struct node
{int h,s,w;
}a[1005];int main()
{int n,h,s;scanf("%d%d%d",&n,&h,&s);for(int i = 1;i <= n;++i)scanf("%d%d%d",&a[i].h,&a[i].s,&a[i].w);for(int i = 1;i <= n;++i){for(int j = h;j >= 0;--j){for(int k = s;k >= 0;--k){if(k >= a[i].s&&j > a[i].h){dp[j][k] = max(dp[j][k],dp[j-a[i].h][k-a[i].s]+a[i].w);}else if(j > a[i].h&&j+k>a[i].s+a[i].h){int res = a[i].s-k;dp[j][k] = max(dp[j][k],dp[j-a[i].h-res][0]+a[i].w);}}}}cout<<dp[h][s]<<endl;return 0;
}

J. Tuition Agent

Problem

Piggy 是一个辅导班的老板,对于第 iii 个客户,Piggy有两个选择:

  1. 花费 XiX_iXi​ 让他变成老师
  2. 花费 YiY_iYi​ 让他变成需要老师来辅导的学生

每给一个学生安排一对一的家教,他就能赚钱。只有等级高的人才可以教等级低的人。其中, 111 是最高的等级。第 iii 个客户有一个编号 RiR_iRi​,每个客户的等级都是不同的。

求得到的最大利润。

Solution

Code

L. Construction of 5G Base Stations

Problem

数轴上 1∼n1\sim n1∼n,每个点都有一个人站在整点上。有 mmm 个基站,每个基站 {x,p[x]}\{x,p[x]\}{x,p[x]},代表位置为 xxx ,每一个人连接该基站成功的概率为 pxp_xpx​。

每个人,都会按照由近及远先左后右的顺序依次尝试连接基站,成功连接基站 iii 的概率是 pip_ipi​ ,如果都
失败了,那么重新再来一遍。

每个基站的开销是连接人数的平方。求所有基站期望运行总代价。

Solution

显然考虑几何概型。

Time

O(n)O(n)O(n)

Code

#include <bits/stdc++.h>using namespace std;
#define int long long
const int N = 1e6 + 7, mod = 998244353;int n, m;
int a[N];
int pre[N], pre2[N], suf[N], suf2[N];
int F, ans;
int p[N], now;int qpow(int a, int b)
{int res = 1;while(b) {if(b & 1) res = res * a % mod;a = a * a % mod;b >>= 1; }return res;
}int inv(int x)
{return qpow(x, mod - 2);
}signed main()
{F = 1;scanf("%lld%lld", &n, &m);for(int i = 1; i <= m; ++ i) {int x, pi;scanf("%lld%lld", &x, &pi);p[x] = pi;F = F * (1 - pi + mod) % mod;}if(n == 1) {puts("1");return 0;}F = inv(1 - F + mod);pre[2] = (1 - p[1] + mod) % mod;pre2[2] = (1 - p[1] + mod) % mod * (1 - p[1] + mod) % mod;now = (1 - p[1] + mod) % mod;for(int i = 3; i <= n; ++ i) {int ansb = (1 - p[i - 1] + mod) % mod * (1 - p[i - 2] + mod) % mod;//先左再右,x在右边now = now * (1 - p[i - 1] + mod) % mod;int ansa = pre[i - 2];pre[i] = (ansb * ansa % mod + ansb + now) % mod;ansa = pre2[i - 2];pre2[i] = (ansb * ansb % mod * ansa % mod + ansb * ansb % mod + now * now % mod) % mod;}suf[n - 1] = (1 - p[n] + mod) % mod;suf2[n - 1] = (1 - p[n] + mod) % mod * (1 - p[n] + mod) % mod;now = (1 - p[n] + mod) % mod;for(int i = n - 2; i >= 1; -- i) {int ansb = (1 - p[i + 1] + mod) % mod * (1 - p[i + 2] + mod) % mod;int tmp = (1 - p[i + 1] + mod) % mod;//先左再右,x在左边now = now * (1 - p[i + 1] + mod) % mod;int ansa = suf[i + 2];suf[i] = (ansb * ansa % mod + tmp + now) % mod;ansa = suf2[i + 2];suf2[i] = (ansb * ansb % mod * ansa % mod + tmp * tmp % mod + now * now % mod) % mod;}for(int i = 1; i <= n; ++ i) {int A = (pre[i] + 1 + suf[i]) % mod * p[i] % mod * F % mod;int B = (pre2[i] + 1 + suf2[i]) % mod * p[i] % mod * p[i] % mod * F % mod * F % mod;ans = (ans + A * A % mod - B + A + mod) % mod;}printf("%lld\n", ans);return 0;
}

M. Matrix Problem

Problem

给定 0/10/10/1 矩阵 CCC,构造两个矩阵 A,BA,BA,B,其中 A,BA,BA,B 矩阵中的 111 形成了完整的不分散的一块四连通块,并且对于 CCC 中所有位置,若是 111 ,则 A,BA,BA,B 对应位置必须都是 111,否则 A,BA,BA,B 之中必须有一个这个位置为 000。
保证 CCC 矩阵的边框都是 000。

Solution

因为保证 CCC 矩阵的一圈全部都是 000 ,所以我们只需要将 AAA 矩阵最左边一列置 111,BBB 矩阵最右边的一列置 111,然后 A,BA,BA,B矩阵奇偶分别负责一半,即A矩阵所有的奇数行(除最后一列)为 111,BBB 矩阵所有的偶数行(除第一列)全部为 111,这样 CCC 矩阵需要的话就直接让 AAA 或者 BBB 为 000 的那个变成 111 即可。

这样构造的关键在于可以完全覆盖1的前提下,使得所有的1连通。前段时间做过一道CF的题,大致意思就是矩阵连通所有的1,那道题就是先横着造一个连续的1(第一行全是1),然后往下垂直连通所有的其他的1,构造思路基本相同。

Code

#include <bits/stdc++.h>
using namespace std;const int N = 500 + 10;
int n,m;
int A[N][N], B[N][N], C[N][N];int main()
{scanf("%d%d",&n, &m);    for(int i = 0;i < n;++i){getchar();for(int j = 0;j < m;++j){char ch = getchar();C[i][j] = ch - '0';}}for(int j = 0;j < n;++j){A[j][0] = 1;B[j][m-1] = 1; }for(int i = 0;i < n;++i){if(i & 1){for(int j = 1;j < m - 1;++j){A[i][j] = 1;}}else{for(int j = 1;j < m - 1;++j){B[i][j] = 1;}}}for(int i = 0;i < n;++i){for(int j = 0;j < m;++j){if(C[i][j] == 1){A[i][j] = B[i][j] = 1;}}}for(int i = 0;i < n;++i){for(int j = 0;j < m;++j){printf("%d",A[i][j]);}puts("");}for(int i = 0;i < n;++i){for(int j = 0;j < m;++j){printf("%d",B[i][j]);}puts("");}return 0;
}

第十一届山东省大学生程序设计竞赛题解(9 / 13)相关推荐

  1. 第十一届山东省大学生程序设计竞赛 L. Construction of 5G Base Stations(概率期望,递推前缀和优化)

    整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 第十一届山东省大学生程序设计竞赛 L. Construction of 5G Base Station ...

  2. ICPC 山东省省赛刷题 第十一届山东省大学生程序设计竞赛 ACM省赛 牛客 DGHM题

    D Dyson Box 题意:有n步,每一步都会出现一个方块,求重力向下和重力向左的方块掉下去的结果图形的周长. 分析:考虑到每个方块周长为4,如果这个方向下有方块的话,就会-2(因为上下两个方块有一 ...

  3. 【B类竞赛】第十一届山东省大学生程序设计竞赛 比赛经历

    序言 去年因为疫情没有举办省赛,导致两年的省赛隔了一年,少参加了一次,血亏. 四月ACM内部选拔赛的时候,用了2017年的山东省省赛题,用个人赛的形式打的,做出来五题,放在当年是可以拿银牌的.队友wz ...

  4. 第十一届山东省大学生程序设计竞赛(热身赛)Mika with Cherry Cake

    #include <bits/stdc++.h> using namespace std ; int n ; struct node {int x , y ; }a[5200] ; int ...

  5. 河南计算机程序大赛,我院成功举办河南省第十一届ACM大学生程序设计竞赛

    5月26-27日,由ACM/ICPC亚洲区竞赛组委会授权.河南省计算机学会主办.我校承办的河南省第十一届ACM大学生程序设计竞赛在我校举行.来自省内30余所本科院校的215支参赛队645名学生参加了竞 ...

  6. 2019河北省大学生程序设计竞赛题解(一)

    2019河北省大学生程序设计竞赛题解(一) B Icebound and Sequence G 点我 H 天神的密码 K 河北美食 L smart robot 下面是一些这次比赛的较简单题目的题解 题 ...

  7. 河南省第十一届ACM大学生程序设计竞赛题目

    河南省第十一届ACM大学生程序设计竞赛题目 A.计划日 B.治安管理 C.山区修路 E.物流配送 F.Gene mutation G.Checkpoints H.Attack City Capture ...

  8. 2016CCPC东北地区大学生程序设计竞赛题解

    以下所有AC题解程序来自"仙客传奇"团队. A. Minimum's Revenge AC的C++语言程序: #include<iostream> using name ...

  9. 2022年GDCPC广东省大学生程序设计竞赛题解

    目录 A 拼图 题解 B FFT 题解:  C 魔法师  题解: D 剪纸 题解:  E 黑白大陆  题解: F 望舒客栈的每日委托 题解:  G Rock&Frog  题解: H 梅花易数 ...

最新文章

  1. 如何顺利度过新人适应期
  2. java架构设计和框架开发有什么区别
  3. Linux文件系统目录
  4. 深圳 | PMCAFF 产品经理第一课,面向3-5年产品经理,全面提升产品战略能力
  5. BADI 修改采购订单的shipping point示例
  6. 区域风云企业之大立-DVR产品的新技术应用
  7. PHP将mysql数据导出为Excel
  8. Visual C++ 图像处理类库CxImage源代码
  9. 金仓数据库 KingbaseES SQL 语言参考手册 (14. SQL语句:COMMIT 到 CREATE LANGUAGE)
  10. VS报错之混合模式程序集是针对“v1.1.4322”版的运行时生成的,在没有配置其他信息的情况下,无法在 4.0 运行时中加载该程序集。...
  11. java pdm 解析_java解析静态AIS原始数据
  12. 删除一个字符串中指定位置上的字符
  13. icmp回复报文_如果目标主机阻塞了,ICMP回显请求报文,我们可以
  14. 《数据库系统概论》课程指南
  15. PAT_乙级1014
  16. 阿里外包java程序员分享,看完你还会去外包吗?
  17. 假如你收到了一封来自Twoo的邮件...
  18. 是男人就下100层【第一层】——高仿微信界面(5)
  19. 另一个程序已锁定文件的一部分,进程无法访问 打不开磁盘“E:\Ubuntu-yun-lianxi\yun2 64 位.vmdk”或它所依赖的某个快照磁盘。 模块“Disk”启动失败。 未能启动虚拟机。
  20. 清洁机器人--沿边测距传感器 sharp psd红外传感器的FOV角度分析

热门文章

  1. 每天2小时,吃透 985博士总结的这份保姆级OpenCV学习笔记(20G高清/PPT/代码)
  2. 30万字,“保姆级”可视化视觉设计优质学习攻略推荐
  3. 【OpenCV 4开发详解】分割图像——Mean-Shift分割算法
  4. 【OpenCV 4开发详解】图像连通域分析
  5. 关于Silverlight_Tools.exe安装不上的问题
  6. 当我们按下电源键,Android 究竟做了些什么?
  7. MySQL删除表及删除表数据操作
  8. MySQL进阶SQL优化
  9. 【转】如何使用VS 2013发布一个可以在Windows XP中独立运行的可执行文件
  10. Java堆外内存的使用