A. Div. 7
题意:给出一个数,要求在改动最少数字的情况下,使其成为7的倍数。
解:7的倍数,每十个数里肯定有一个。暴力即可。
代码:

#include <bits/stdc++.h> using namespace std; #define ll long long #define maxx 200005 #define eps 0.00000001 #define inf 0x7fffffff #define mod 998244353 //#define int long long int n,k; signed main() { int T; scanf("%d",&T); while(T--){ scanf("%d",&n); if(n%7==0) { printf("%d\n",n); continue; } int down=n/10*10; for(int i=down;i<down+10;i++) { if (i % 7 == 0) { printf("%d\n", i); break; } } } return 0; }
B - Minority
题意:给出一个01串,可以从中选择一个子数组,删去0和1中数字个数少的那一方,操作一次,问最多删除多少数字。
解:全选上,如果个数相等那随便减一个。
代码:

#include <bits/stdc++.h> using namespace std; #define ll long long #define maxx 200005 #define maxn 100005 #define maxm 200005 #define eps 0.00000001 #define inf 0x7fffffff #define mod 998244353 //#define int long long char s[maxx]; int n; signed main() { int T; scanf("%d",&T); while(T--){ scanf("%s",s+1); n= strlen(s+1); int ans=0,num0=0,num1=0; for(int i=1;i<=n;i++){ if(s[i]=='0') num0++; else num1++; } if(num0!=num1) ans=min(num0,num1); else ans=num0-1; printf("%d\n",ans); } return 0; }
C - Kill the Monster
题意:你有hc点血,dc点攻;怪物有hm点血,dm点攻。有k次机会,每次可以选择加a点血或者w点攻。你先手,轮着打对方,血线降到0及以下输,问你能不能赢。
解:一开始看错了。。。还以为给怪物加血。治好眼睛后列了个式子,重点在血和攻上怎么分配。打开题目一看k一共就2e5,太好了枚举吧。
代码:

#include <bits/stdc++.h> using namespace std; #define ll long long #define maxx 200005 #define maxn 100005 #define maxm 200005 #define eps 0.00000001 #define inf 0x7fffffff #define mod 998244353 //#define int long long ll hc,dc,hm,dm; ll k,w,a; signed main() { int T; scanf("%d",&T); while(T--){ scanf("%lld%lld%lld%lld",&hc,&dc,&hm,&dm); scanf("%lld%lld%lld",&k,&w,&a); ll c,m; int flag=0; for(int i=0;i<=k;i++){ ll h=hc+a*i; ll d=dc+w*(k-i); c=h/dm+(h%dm!=0); m=hm/d+(hm%d!=0); if(c>=m) flag=1; } if(flag) printf("YES\n"); else printf("NO\n"); } return 0; }
D. Make Them Equal
题意:数组a有n个元素,初始值为1。每次操作可以任选一个正整数x,使a[i]=a[i]+a[i]/x,当a[i]与b[i]相等时,获得价值c[i]。最多执行k次操作,求获得最大价值。
解:目测用这种方法可以将1变成任意一个数。如果求出最小步数,那跑一遍背包就完了。现在来求最小步数。一开始贪心,WA掉了。一个数能变成另外几个数,显然应该用最短路。
代码:

#include <bits/stdc++.h> using namespace std; #define ll long long #define maxx 1000005 #define maxn 1005 #define eps 0.00000001 #define inf 0x7fffffff #define mod 998244353 //#define int long long int n,k; int b[maxn],c[maxn],w[maxn]; int vis[maxn]={0}; int dp[maxx]={0}; void spfa(){ for(int i=1;i<=1000;i++) w[i]=inf; queue<int> q; q.push(1); w[1]=0;vis[1]=1; while(!q.empty()){ int now=q.front(); q.pop(); vis[now]=0; for(int i=1;i<=now;i++){ int to=now/i+now; if(w[to]>w[now]+1){ w[to]=w[now]+1; if(!vis[to]){ q.push(to); vis[to]=1; } } } } } signed main() { int T; scanf("%d",&T); spfa(); while(T--){ scanf("%d%d",&n,&k); for(int i=0;i<=k;i++) dp[i]=0; for(int i=1;i<=n;i++) scanf("%d",&b[i]); for(int i=1;i<=n;i++) scanf("%d",&c[i]); for(int i=1;i<=n;i++) { for (int j = k; j >= w[b[i]]; j--) dp[j]=max(dp[j],dp[j-w[b[i]]]+c[i]); } printf("%d\n",dp[k]); } return 0; }
E. Spanning Tree Queries
题意:给出一张图和k个询问x,对于每个询问,求将其所有边变为 |wi-x| 后的最小生成树。
解:显然对于每个询问都求一边会T。但是最小生成树好像没什么别的算法,那就从询问下手。对于原来的生成树,现在加入一个x,假设小于x的边有 x1 条,大于x的边有 x2 条,原边权和对应为 s1 + s2 ,现对应和为 s1 - s2 + ( x2 - x1 ) * x ,也就是说,x变化后最小生成树的选择与x1和x2有关,也就是x在原最小生成树中的位置。现在生成次数与变动次数有关,考虑生成次数。k最大到1e7,w最大到1e8,数据类似随机生成,也就是说变动次数不会太大,可以做(但我不会算)。但是这个思路代码贼难写,看了别人解法。大佬直接考虑边,对于两条边a和b,x<(a+b)/2+1 时生成树不变,反之需要重新算。也就是说,先把所有会导致变动的点算出来,会好写很多。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话