パナソニックグループ プログラミングコンテスト2024(ABC 375)

news/2024/10/13 9:42:32
形象理解这一场的 C

A.Seats \(\text{diff }20\)

对给定序列 \(S\) 找出 \(i\) 的个数,使得 \(S_{i}=0,S_{i+1}=1,S_{i+2}=0\)

#define int long long
string x;signed main(){int n;cin>>n;cin>>x;int ans=0;for(int i=0;i<=(int)x.length()-3;++i){if(x[i]=='#' and x[i+2]=='#' and x[i+1]=='.'){ans++;}}cout<<ans;
}

B.Traveling Takahashi Problem \(\text{diff }65\)

给定平面上 \(N\) 个点,求从原点出发按编号顺序走完 \(N\) 个点并走回原点的直线距离之和

#include<bits/stdc++.h>
using namespace std;
#define int long long
long double dist(int x1,int y1,int x2,int y2){return sqrtl((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
}
int n;
int nx=0,ny=0;
long double ans=0;
signed main(){cin>>n;for(int i=1;i<=n;++i){int x,y;cin>>x>>y;ans+=dist(nx,ny,x,y);nx=x;ny=y;}ans+=dist(nx,ny,0,0);printf("%.20Lf",ans);
}

C.Spiral Rotation \(\text{diff }972\)

给定一个 \(N\times N\)\(01\) 矩阵,\(N\) 为偶数,对每个 \(i\in[1,\frac{N}{2}]\) 执行如下操作

  • 选择所有 \(i\le x,y\le N-i+1\),将 \((y,N-x+1)\) 上的值替换为 \((x,y)\) 上的值

对于每一个 \(i\),对所有 \((x,y)\) 的替换同时发生,也即在每一个 \(i\) 内不存在覆盖的情况
输出最终的矩阵

\(N\le 10^3\)

通过手摸可以发现,对单独的一个 \(i\) 来说,相当于四个一组发生旋转

点击查看

但是这里有一个 \(i\in[1,\frac{N}{2}]\),这其实相当于是分层的,先整体转,再转第二层和以内的,再转第三层和以内的,相当于第一层转一圈,第二层转两圈,以此类推

可以发现转四圈不会影响结果,因此第 \(k\) 层转 \(k\mod 4\) 圈就行了

#include<bits/stdc++.h>
using namespace std;
#define int long long
int n;
char mp[3001][3001];
bool vis[3001][3001];
signed main(){cin>>n;for(int i=1;i<=n;++i){for(int j=1;j<=n;++j){cin>>mp[i][j];}}for(int k=1;k<=n/2;++k){for(int i=k;i<=n-k+1;++i){if(!vis[i][k]){if(k%4==1){int x1=i,y1=k;int x2=y1,y2=n-x1+1;int x3=y2,y3=n-x2+1;int x4=y3,y4=n-x3+1;char tmp=mp[x4][y4];mp[x4][y4]=mp[x3][y3];mp[x3][y3]=mp[x2][y2];mp[x2][y2]=mp[x1][y1];mp[x1][y1]=tmp;vis[x1][y1]=true;vis[x2][y2]=true;vis[x3][y3]=true;vis[x4][y4]=true;}else if(k%4==2){int x1=i,y1=k;int x2=y1,y2=n-x1+1;int x3=y2,y3=n-x2+1;int x4=y3,y4=n-x3+1;char tmp=mp[x4][y4];mp[x4][y4]=mp[x3][y3];mp[x3][y3]=mp[x2][y2];mp[x2][y2]=mp[x1][y1];mp[x1][y1]=tmp;tmp=mp[x4][y4];mp[x4][y4]=mp[x3][y3];mp[x3][y3]=mp[x2][y2];mp[x2][y2]=mp[x1][y1];mp[x1][y1]=tmp;vis[x1][y1]=true;vis[x2][y2]=true;vis[x3][y3]=true;vis[x4][y4]=true;}else if(k%4==3){int x1=i,y1=k;int x2=y1,y2=n-x1+1;int x3=y2,y3=n-x2+1;int x4=y3,y4=n-x3+1;char tmp=mp[x4][y4];mp[x4][y4]=mp[x3][y3];mp[x3][y3]=mp[x2][y2];mp[x2][y2]=mp[x1][y1];mp[x1][y1]=tmp;tmp=mp[x4][y4];mp[x4][y4]=mp[x3][y3];mp[x3][y3]=mp[x2][y2];mp[x2][y2]=mp[x1][y1];mp[x1][y1]=tmp;tmp=mp[x4][y4];mp[x4][y4]=mp[x3][y3];mp[x3][y3]=mp[x2][y2];mp[x2][y2]=mp[x1][y1];mp[x1][y1]=tmp;vis[x1][y1]=true;vis[x2][y2]=true;vis[x3][y3]=true;vis[x4][y4]=true;}}}for(int j=k+1;j<=n-k;++j){if(!vis[k][j]){if(k%4==1){int x1=k,y1=j;int x2=y1,y2=n-x1+1;int x3=y2,y3=n-x2+1;int x4=y3,y4=n-x3+1;char tmp=mp[x4][y4];mp[x4][y4]=mp[x3][y3];mp[x3][y3]=mp[x2][y2];mp[x2][y2]=mp[x1][y1];mp[x1][y1]=tmp;vis[x1][y1]=true;vis[x2][y2]=true;vis[x3][y3]=true;vis[x4][y4]=true;}else if(k%4==2){int x1=k,y1=j;int x2=y1,y2=n-x1+1;int x3=y2,y3=n-x2+1;int x4=y3,y4=n-x3+1;char tmp=mp[x4][y4];mp[x4][y4]=mp[x3][y3];mp[x3][y3]=mp[x2][y2];mp[x2][y2]=mp[x1][y1];mp[x1][y1]=tmp;tmp=mp[x4][y4];mp[x4][y4]=mp[x3][y3];mp[x3][y3]=mp[x2][y2];mp[x2][y2]=mp[x1][y1];mp[x1][y1]=tmp;vis[x1][y1]=true;vis[x2][y2]=true;vis[x3][y3]=true;vis[x4][y4]=true;}else if(k%4==3){int x1=k,y1=j;int x2=y1,y2=n-x1+1;int x3=y2,y3=n-x2+1;int x4=y3,y4=n-x3+1;char tmp=mp[x4][y4];mp[x4][y4]=mp[x3][y3];mp[x3][y3]=mp[x2][y2];mp[x2][y2]=mp[x1][y1];mp[x1][y1]=tmp;tmp=mp[x4][y4];mp[x4][y4]=mp[x3][y3];mp[x3][y3]=mp[x2][y2];mp[x2][y2]=mp[x1][y1];mp[x1][y1]=tmp;tmp=mp[x4][y4];mp[x4][y4]=mp[x3][y3];mp[x3][y3]=mp[x2][y2];mp[x2][y2]=mp[x1][y1];mp[x1][y1]=tmp;vis[x1][y1]=true;vis[x2][y2]=true;vis[x3][y3]=true;vis[x4][y4]=true;}}}}for(int i=1;i<=n;++i){for(int j=1;j<=n;++j){cout<<mp[i][j];}cout<<'\n';}
}

D.ABA \(\text{diff }658\)

给定一个字符串 \(S\),求满足下列条件的 \((i,j,k)\) 对数

  • \(i\lt j\lt k\)
  • \(S_i,S_j,S_k\) 能构成回文

\(|S| \le 2\times 10^5\)

其实也就是找 \(S_i=S_k\) 的对数,然后中间填什么都行

注意到两个相等的数,如果位置分别为 \(i,j\),那么它们中间夹着的任何一个数都能造成贡献,也即贡献为 \(j-i-1\)

如果枚举到一个数 \(S_i\) 时,有 \(k\) 个数(\(S_{j1},S_{j2}\cdots\))与其相等,则对答案的贡献应该是 \((S_i-S_{j1}-1)+(S_i-S_{j2}-1)\cdots=k(S_i-1)-\sum S_{j}\)

因此维护前缀和即可

#include<bits/stdc++.h>
using namespace std;
#define int long long
int possum[27];
int poscnt[27];
string x;
int ans=0;
signed main(){cin>>x;for(int i=0;i<=(int)x.length()-1;++i){ans+=max(0ll,(i-1)*poscnt[x[i]-'A']-possum[x[i]-'A']);poscnt[x[i]-'A']++;possum[x[i]-'A']+=i;}cout<<ans;
}

E.3 Team Division \(\text{diff }1424\)

有三支队伍和 \(N\) 个人,每支队伍初始有一定人数,每个人有权值 \(B_i\),可以移动任意队伍中的人,问三支队伍的权值和相等所需的最小移动次数

\(N\le 100,\sum B_i\le 1500\)

首先注意到

  • \(\sum B_i \not \equiv 0\pmod 3\) 无解

考虑换种思路做,清空所有队里的人,然后一个一个往里填,如果当前填的人本来就在这个队里,则对移动次数无贡献,否则有 \(1\) 的贡献

然后,注意到最终每个队的总和不超过 \(\frac{\sum B_i}{3}=500\),因此设计 \(f_{i,j,k}\) 表示放到第 \(i\) 个人,第一队有 \(j\) 的权值和,第二队有 \(k\) 的权值和的最少交换次数(第三队可以用 \(\sum B_i-j-k\) 算出来)

直接枚举每个人填数即可

最后从 \(f_{n,\frac{\sum}{3},\frac{\sum}{3},\frac{\sum}{3}}\) 统计答案

#include<bits/stdc++.h>
using namespace std;
#define int long long
int n;
int a[101],b[101];
int f[101][501][501];
int sum[5];
int tot;
signed main(){cin>>n;for(int i=1;i<=n;++i){cin>>a[i]>>b[i];sum[a[i]]+=b[i];tot+=b[i];}if(tot%3!=0){cout<<-1;return 0;}memset(f,0x3f,sizeof f);f[0][0][0]=0;for(int i=1;i<=n;++i){for(int j=0;j<=tot/3;++j){for(int k=0;k<=tot/3;++k){if(j>=b[i]) f[i][j][k]=min(f[i][j][k],f[i-1][j-b[i]][k]+(a[i]!=1));if(k>=b[i]) f[i][j][k]=min(f[i][j][k],f[i-1][j][k-b[i]]+(a[i]!=2));if(tot-j-k>=b[i]) f[i][j][k]=min(f[i][j][k],f[i-1][j][k]+(a[i]!=3));}}}if(f[n][tot/3][tot/3]>=0x3f3f3f3f3f3f3f3f){cout<<-1;return 0;}cout<<f[n][tot/3][tot/3]<<endl;
}

F.Road Blocked \(\text{diff }1546\)

无向图中实现如下操作

  • 1 i 删除第 \(i\) 条边
  • 2 x y 查询 \(x,y\) 两点的最短路径长度

\(N\le 300,Q\le 2\times 10^5\)

有删边,应该倒过来处理询问

然后考虑加边怎么处理变化

用 DP 的思路,加了边之后,只有经过这条边两个端点的路径才能有可能改变,因为 \(N\) 比较小,因此考虑将这条新加的边的两个端点当中转点,枚举所有点对的路径来更新

类似弗洛伊德(其实就是弗洛伊德)

#include<bits/stdc++.h>
using namespace std;
#define int long long
int f[301][301];
int n,m,q;
struct edge{int l,r,w;
}e[300*300+1];
struct opera{int op;int id;int x,y;
}op[200001];
bool vis[300*300+1];
vector<int>ans;
signed main(){ios::sync_with_stdio(false);cin>>n>>m>>q;for(int i=1;i<=m;++i){int x,y,z;cin>>x>>y>>z;e[i]={x,y,z};}for(int i=1;i<=q;++i){cin>>op[i].op;if(op[i].op==1){cin>>op[i].id;vis[op[i].id]=true;}else{cin>>op[i].x>>op[i].y;}}memset(f,0x3f,sizeof f);for(int i=1;i<=m;++i){if(!vis[i]){f[e[i].l][e[i].r]=min(f[e[i].l][e[i].r],e[i].w);f[e[i].r][e[i].l]=min(f[e[i].r][e[i].l],e[i].w);}}for(int k=1;k<=n;++k){for(int i=1;i<=n;++i){for(int j=1;j<=n;++j){f[i][j]=min(f[i][j],f[i][k]+f[k][j]);}}}for(int t=q;t>=1;--t){if(op[t].op==1){f[e[op[t].id].l][e[op[t].id].r]=min(f[e[op[t].id].l][e[op[t].id].r],e[op[t].id].w);f[e[op[t].id].r][e[op[t].id].l]=min(f[e[op[t].id].r][e[op[t].id].l],e[op[t].id].w);// cout<<"add "<<e[op[t].id].l<<" "<<e[op[t].id].r<<endl;for(int i=1;i<=n;++i){for(int j=1;j<=n;++j){f[i][j]=min(f[i][j],f[i][e[op[t].id].l]+f[e[op[t].id].l][j]);}}for(int i=1;i<=n;++i){for(int j=1;j<=n;++j){f[i][j]=min(f[i][j],f[i][e[op[t].id].r]+f[e[op[t].id].r][j]);}}}if(op[t].op==2){if(f[op[t].x][op[t].y]>=0x3f3f3f3f3f3f3f3f){ans.push_back(-1);}else ans.push_back(f[op[t].x][op[t].y]);}}std::reverse(ans.begin(),ans.end());for(int i:ans){cout<<i<<"\n";}
}

G.Road Blocked 2 \(\text{diff }2014\)

对给定无向图判断:

  • 对所有 \(i\in[1,m]\),如果将第 \(i\) 条边删去,\(1\)\(N\) 的最短路径是否发生变化

\(N,M\le 2\times 10^5\)

看的第二篇题解

判断这个其实就是判断一条边是不是会被所有 \(1\)\(N\) 的最短路经过

我们可以根据 \(dis\) 判一下边 \((x,y)\) 是否在最短路上:

\[dis_{1,x}+w_{x,y}+dis_{y,N}=dis_{1,N} \]

或者反着来也行,但是这样我们就能判断其是否在最短路上

然后我们需要判断一条边是否为所有最短路的必经边,判断一条边被几条最短路径经过是不容易的,但是判断 \(1\) 到一个节点有几条最短路径是容易的

因此我们可以这样判断:

  • 如果 \(1\)\(x\)\(c_x\) 条最短路径,到 \(N\)\(c_N\) 条最短路径,\(N\)\(y\)\(c_y\) 条最短路径,则如果 \(c_x\times c_y=c_N\),那么就说明边 \((x,y)\) 是最短路必经边

这么做有一个好处就是分别拿 \(1,N\) 跑两边最短路就能统计答案

#include <bits/stdc++.h>
using namespace std;
#define int long long
int n,m; 
const int p=1e9+7;
struct __edge{int to,w;
};
vector<__edge>e[200001];
struct ___edge{int from,to,w;
};
___edge edge[200001];
int dis[2][200001];
bool vis[2][200001];
int cnt[2][200001];
struct node{int id,dis;bool operator <(const node &A)const{return dis>A.dis;}
};
priority_queue<node>q;
void dij(int s,int id){memset(dis[id],0x3f,sizeof dis[id]);memset(vis[id],0,sizeof vis[id]);memset(cnt[id],0,sizeof cnt[id]);dis[id][s]=0;cnt[id][s]=1;q.push({s,dis[id][s]});while(!q.empty()){node u=q.top();q.pop();if(dis[id][u.id]<u.dis) continue;if(vis[id][u.id]) continue;vis[id][u.id]=true;for(__edge i:e[u.id]){if(dis[id][i.to]>dis[id][u.id]+i.w){dis[id][i.to]=dis[id][u.id]+i.w;q.push({i.to,dis[id][i.to]});cnt[id][i.to]=cnt[id][u.id];}else if(dis[id][i.to]==dis[id][u.id]+i.w){cnt[id][i.to]=(cnt[id][i.to]+cnt[id][u.id])%p;}}}
}
signed main(){cin>>n>>m;for (int i=1;i<=m;i++){int u,v,w;cin>>u>>v>>w;e[u].push_back({v,w});e[v].push_back({u,w});edge[i]={u,v,w};}dij(1,0);dij(n,1);for(int i=1;i<=m;++i){int u=edge[i].from,v=edge[i].to,w=edge[i].w;if((dis[0][u]+w+dis[1][v]==dis[0][n] and cnt[0][u]*cnt[1][v]%p==cnt[0][n])or (dis[0][v]+w+dis[1][u]==dis[0][n] and cnt[0][v]*cnt[1][u]%p==cnt[0][n])){cout<<"Yes\n";}else{cout<<"No\n";}}
}

林妹妹,赢!

哥们图床现在比较富有

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.ryyt.cn/news/70986.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈,一经查实,立即删除!

相关文章

揭秘 FineVideo 数据集构建的背后的秘密

开放视频数据集稀缺,因此减缓了开源视频 AI 的发展。为此,我们构建了 FineVideo,这是一个包含 43,000 个视频的数据集,总时长为 3,400 小时,并带有丰富的描述、叙事细节、场景分割和问答对。 FineVideo 包含高度多样化的视频和元数据集合,使其成为训练模型理解视频内容、…

财务人的数字化转型

随着全球经济的变化,所有行业从过去的红利,过渡到向管理要红利,数字技术为经营和财务效率带来了令人惊喜的助推力,财务数字化成为企业转型的一个重要方向。 公司战略转型背后,财务组织如何长期落地? 数字化转型带来哪些实质性效益? 财务共享中心数字化建设现状 不同阶段…

多校 A 层冲刺 NOIP2024 模拟赛 06

多校A层冲刺NOIP2024模拟赛06 T 小 Z 的手套(gloves) 签到题 答案显然具有单调性,排序后二分答案即可。 T 小 Z 的字符串(string) 签到题 注意到 \(n\) 较小,可以使用 \(O(n^3)\) 的算法,直接上大 \(DP\)。 设计状态 \(f_{i,j,k,0/1/2}\) 表示从左往右填到 \(i\) 位,已…

Panasonic Programming Contest 2024(AtCoder Beginner Contest 375)

Panasonic Programming Contest 2024(AtCoder Beginner Contest 375)\(A\) A - Seats \(AC\)基础字符串。点击查看代码 int main() {int n,ans=0,i;string s;cin>>n>>s;for(i=0;i<n;i++){ans+=(s[i]==#&&s[i+1]==.&&s[i+2]==#&&i+2&l…

读数据工程之道:设计和构建健壮的数据系统07数据架构的原则

数据架构的原则1. 企业架构 1.1. 企业架构有很多子集,包括业务、技术、应用程序和数据 1.2. TOGAF1.2.1. The Open Group Architecture Framework,是The Open Group的一个标准1.2.2. 被誉为当今使用最广泛的架构框架1.2.3. 定义1.2.3.1. “企业架构”上下文中的术语“企业”可…

InputTip:输入法状态提示工具,让你的输入更高效

InputTip 是一个输入法状态(中文/英文/大写锁定)提示工具,免费开源InputTip 是一个输入法状态(中文/英文/大写锁定)提示工具,免费开源,基于 AutoHotKey 开发。 ‍ 介绍 ​ 官网:https://inputtip.pages.dev 开源在 GitHub:https://github.com/abgox/InputTip 和 Gite…

Nexpose 6.6.272 发布下载,新增功能概览

Nexpose 6.6.272 for Linux & Windows - 漏洞扫描Nexpose 6.6.272 for Linux & Windows - 漏洞扫描 Rapid7 Vulnerability Management, released Oct 03, 2024 请访问原文链接:https://sysin.org/blog/nexpose-6/ 查看最新版。原创作品,转载请保留出处。 作者主页:s…