2.【LGR-148-Div.3】洛谷基础赛 #1 & MGOI Round I
【LGR-148-Div.3】洛谷基础赛 #1 & MGOI Round I
据说是普及组难度?
T1 P9502 『MGOI』Simple Round I | A. 魔法数字
『MGOI』Simple Round I | A. 魔法数字
题目描述
初级魔法士小 M 的魔法数字是
给定一个正整数
- 又双叒叕是个水题,
然后被又双叒叕水题爆切。。。。。。 - 只要判断
是否为偶数,并且不能正好是 的 次方,然后输出即可。
#include<bits/stdc++.h> using namespace std; int main() { int n,i; cin>>n; if(int(log2(n))%2==0&&int(log2(n))!=log2(n)) cout<<(int)log2(n); else if(int(log2(n))%2==1) cout<<(int)log2(n)-1; else cout<<int(log2(n)-2); }
T2 P9503 『MGOI』Simple Round I | B. 魔法照相馆
题目描述
小 M 正在准备入学所必需的魔法士证件,因此他来到了纵深巷的魔法照相馆。
在等待的时候,小 M 注意到魔法照相馆有三个幕布,颜色从左到右分别是红色、蓝色和白色。店主 zx 先生会根据客人的需求拉上或拉下这三个幕布,如下图所示:
幕布摆放在左边,按照红蓝白的顺序排列。人则坐在幕布右边,而 zx 先生则站在最右边给人拍照。幕布从右往左数,第一个没有拉上的幕布颜色将成为照片的背景颜色。
每次 zx 先生拉上或拉下一个幕布都需要消耗一个时间单位,而拍照不消耗时间。小 M 已经知道了他前面所有总共
- 水题,只要模拟状态,再对号入座,就轻轻松松
了。 - (其中红色幕布不会拉上去)
#include<bits/stdc++.h> using namespace std; int main() { int n,i,sum=0,zt=111; char q; cin>>n; for(i=1;i<=n;i++) { cin>>q; //111 110 101 100 if(q=='W'&&(zt==101||zt==111))continue; else if(q=='B'&&(zt==110))continue; else if(q=='R'&&(zt==100))continue; if(q=='W') { if(zt==110)zt=111,sum++; else if(zt==100)zt=101,sum++; } if(q=='B') { if(zt==111||zt==100)zt=110,sum++; else if(zt==101)zt=110,sum+=2; } if(q=='R') { if(zt==111)zt=100,sum+=2; else if(zt==110||zt==101)zt=100,sum++; } } cout<<sum; }
- 将各个幕布的状态枚举,拉下为
,拉上为 。
T3P9504 『MGOI』Simple Round I | C. 魔法禁林
题目描述
开学的第一天,小 M 迫不及待地计划着前往神秘的禁林。
小 M 拥有两个重要的属性,魔力值和生命值。非常特别的是,初始时,这两个值可以由小 M 任意决定。
禁林可以看作一张
每经过一条边,小 M 的魔力值都会减去 1。同时,每条边上有一个具有攻击力属性的魔兽,小 M 要与之战斗。若小 M 经过这条边之前的魔力值为
小 M 需要保证,当他的魔力值消耗完时,他的生命值为 0,且此时走到
你需要求出小 M 初始时需要的最小生命值。
【数据范围】
对于所有数据,
Subtask | 分值 | |||
---|---|---|---|---|
- 一开始觉得完全打不了,但是还是试了试。
- 首先使用
求最短路,但是不知道走每条边的状态,后来想到倒推,以终点 为起点,推回起点 。
代码
#include<bits/stdc++.h> using namespace std; int n,m,s,t; struct aa { int nxt,to,w; }e[1100001]; int cnt=0,head[100001]; void add(int u,int v,int w) { e[++cnt]={head[u],v,w}; head[u]=cnt; } long double dis[100011]; int stp[100011]; int vis[100011]; struct cmp { bool operator() (int &a,int &b) const { return dis[a]>dis[b]; } }; void dijkspfa(int x) { priority_queue<int,vector<int>,cmp>q; int i,j,k; memset(vis,0,sizeof(vis)); for(i=1;i<=n;++i)dis[i]=0x7f7f3f3f3f3f3f,stp[i]=0; q.push(x); dis[x]=0; while(!q.empty()) { k=q.top(),q.pop(); if(!vis[k]) { vis[k]=1; for(i=head[k];i;i=e[i].nxt) { int to=e[i].to; if(dis[to]>=dis[k]*1.0+e[i].w/(stp[k]+1.0)) { stp[to]=stp[k]+1; dis[to]=dis[k]*1.0+e[i].w/stp[to]*1.0; q.push(to); } } } } } int main() { int i,j,k,u,v,w; cin>>n>>m>>s>>t; for(i=1;i<=m;i++) { cin>>u>>v>>w; add(u,v,w),add(v,u,w); } dijkstra(t); cout<<(int)(ceil(dis[s])); }
(虽然试试就逝世,但是出题人的数据怎么如此之氵,这也能骗30分)...
测评记录
- 实际上,生命值不是
而是 。 有什么特性,自动向下取整。于是当一个数除以一个大于它的数时,值为 。 - 因此可以让每条边被经过不超过
( )遍。当一条边被经过 次时,求现有最小值与其值的最小值。最后输出即可 - (
话说)。 是什么东西,怎么这么强。。。
附上
#include<bits/stdc++.h> using namespace std; int n,m,s,t; struct aa { int nxt,to,w; }e[1100001]; struct ee { int cnt,x; }k;queue<ee>q; int cnt=0,head[100001]; void add(int u,int v,int w) { e[++cnt]={head[u],v,w}; head[u]=cnt; } int dis[222][230011]; bool vis[222][230011]; int minn=0x7f7f7f00; void dijkstra(int x) { int i,j; memset(vis,0,sizeof(vis)); for(i=1;i<=101;++i)for(j=1;j<=n;++j)dis[i][j]=0x7f7f7f7f; q.push({1,x}); dis[1][x]=0; int v=0; while(!q.empty()) { k=q.front(),q.pop(); int y=k.cnt; int p=k.x; if(y>100) { minn=min(minn,dis[y][p]); } for(i=head[p];i;i=e[i].nxt) { int to=e[i].to; if(dis[y+1][to]>=dis[y][p]*1.0+e[i].w/y) { dis[y+1][to]=dis[y][p]*1.0+e[i].w/y; if(!vis[y+1][to]) q.push({y+1,to}),vis[y+1][to]=1; } } } } int main() { int i,j,k,u,v,w; cin>>n>>m>>s>>t; for(i=1;i<=m;i++) { cin>>u>>v>>w; add(u,v,w),add(v,u,w); } dijkstra(t); for(i=1;i<=101;i++)minn=min(minn,dis[i][s]); cout<<minn; }
T4P9505 『MGOI』Simple Round I | D. 魔法环
- 赛后我们首先
查看题解,原来本蒟蒻与大佬之间的差距如此之大。。 - 由于精灵围成了一个环,因此首先考虑破环为链
-
状态转移方程
-
-
表示这一步激活 点,上一个激活 点使当前值变化的量。 -
-
这时复杂度为
,轻轻松松 ,观察状态转移方程可知,其于 即已激活点数无关,所以如果 时可以直接从 转移,此时复杂度为 -
还有一个结论,即一定激活点
。因为如果未激活点 ,由于至少要激活 个精灵,因此未激活的精灵总能找到魔力值大于 的精灵。因此点 未产生贡献(甚至负贡献)。 -
所以直接由
为起点,而此时复杂度为 ,可以通过此题。- 关于大佬们的破环为链
for(int i=1;i<=n;i++) scanf("%d",&q[i]); for(int i=1;i<=n;i++) if(!q[i]) pos=i; for(int i=1;i<=n;i++) p[i]=q[(i+pos-1-1)%n+1];
关于我的破环为链
for(i=0;i<n;++i) { cin>>a[i]; if(!a[i])res=i; } for(i=res,j=1;j<=n;++i,++j) { s[j]=a[i]; if(i==n-1)i=-1; }
(明显不如原神)
#include<bits/stdc++.h> #define int long long using namespace std; int n,m,s[3011],t,ans=0x7f7f7f7f,p; int f[3022][111],a[3011]; inline int getv(int l,int r) { return ((r-l)*(r-l-1)>>1)*max(s[l],s[r])+s[r]*s[r]; } signed main(void) { ios::sync_with_stdio(0);cin.tie(0);cout.tie(0); register int i,j,k; int u,v,w,res; cin>>n>>m; for(i=0;i<n;++i) { cin>>a[i]; if(!a[i])res=i; } for(i=res,j=1;j<=n;++i,++j) { s[j]=a[i]; if(i==n-1)i=-1; } memset(f,0x7f,sizeof(f)); f[1][1]=0; for(i=1;i<=n;++i) for(j=2;j<=min(i,m);++j) for(k=1;k<i;++k) { f[i][j]=min(f[i][j],f[k][j-1]+getv(k,i)); if(j==m)f[i][j]=min(f[i][j],f[k][j]+getv(k,i)); } ans=LLONG_MAX; for(i=1;i<=n;++i)ans=min(ans,f[i][m]+getv(i,n+1)); cout<<ans; }
- dp数组求最小值一定要初始化为
,并且将始状态赋值为0。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】