A. Elections

链接:A
题意:给三个数,输出每个数要变成最大值至少要加的值
做法:用max模拟一下就好

#include <bits/stdc++.h> using namespace std; int main(){  int t;cin>>t; while (t--){  int a,b,c;cin>>a>>b>>c; cout<<max(max(b,c)-a+1,0)<<" "<<max(max(a,c)-b+1,0)<<" "<<max(max(a,b)-c+1,0)<<endl; } } 

B. Make it Divisible by 25

链接:B
题意:给一串数,去掉任意数后使其变为25的倍数,求最少去掉几个数
做法:数学规律+暴力枚举。发现规律25的倍数末尾必为00,25,50,75,故暴力枚举、用双指针往后找越接近末尾的子序列,去掉的数=右指针到末尾的数+左右指针中间的数,再取最小值即可

#include <bits/stdc++.h> #define INF 0x7f7f7f7f #define int long long #define IOS ios::sync_with_stdio(0);cin.tie(0);cout.tie(0); using namespace std; string s[] = { "00","25","50","75"}; signed main(){  IOS //for (int i=25;i<=100000;i+=25) cout<<i<<endl; int t;cin>>t; while (t--){  string ss;cin>>ss; int len = ss.length(); int ans = INF; for (int i=0;i<4;i++){  int l = -1,r = -1; for (int k=0;k<ss.size();k++){  if (ss[k]==s[i][1]){  r = k; } }//右指针先找末尾数的位置 if (r!=-1){  for (int k=0;k<ss.size()&&k<r;k++){  if (ss[k]==s[i][0]){  l = k; } } } //cout<<"l = "<<l<<" r = "<<r<<endl; if (l!=-1&&r!=-1) {  ans = min(len-r-1+r-l-1,ans); } } cout<<ans<<endl; } } 

C. Save More Mice

链接:C
题意:x坐标轴上,一只猫在零点,k只老鼠在正坐标轴上,n坐标点有一个洞。每个时间单位可以让一只老鼠向右移一格,同时猫也向右一格,若猫移到的坐标上有一只老鼠,这只老鼠就会被吃。老鼠进洞就不会被吃。问有多少只不会被吃。
做法:经典贪心+模拟。对老鼠坐标排序,越接近洞的老鼠先走,累计时间为前几只老鼠到洞的距离之和,当前老鼠到洞的距离<累计时间即不会被吃

#include <bits/stdc++.h> #define IOS ios::sync_with_stdio(0);cin.tie(0);cout.tie(0); using namespace std; int main(){  IOS int t;cin>>t; while (t--){  int n,k;cin>>n>>k; int x[k+1]; int ans = 0,sum = 0,c = 0; for (int i=1;i<=k;i++) cin>>x[i]; sort(x+1,x+k+1); for (int i=k;i>=1;i--){  int t = n - x[i]; if (c<x[i]) ans++; else break; c += t; } cout<<ans<<endl; } } 

D1. All are Same

链接:D1
题意:给偶数个数,选择一些数减少k的整数倍,使所有数相等,问k的最大值(k任意大则输出-1)
做法:差分+数学 。所有数相等=差分为0,k为最大的使所有差分数组能够被整除的数。故排序后去重求差分的最大公约数即可。

#include <bits/stdc++.h> #define int long long using namespace std; int gcd(int a,int b){  return b?gcd(b,a%b):a; } signed main(){  int t;cin>>t; while (t--){  int n;cin>>n; vector<int>a; for (int i=1;i<=n;i++){  int x;cin>>x; a.push_back(x); } if (n==1){  cout<<0<<endl; continue; }//只有一个数 直接输出0 sort(a.begin(),a.end()); a.erase(unique(a.begin(),a.end()),a.end()); if (a.size()==1){ //去重后只有一个数,说明所有数相等,k取任意大,输出-1 cout<<-1<<endl; continue; } int x = a[1] - a[0]; for (int i=2;i<a.size();i++){  x = gcd(a[i]-a[i-1],x); } cout<<x<<endl; } } 

E. Gardener and Tree

链接:E
题意:给一个无向树图,有n个结点n-1条边,进行k次操作,每次操作删去叶子结点。问剩下几个结点
做法:拓扑+bfs。将入度为0的为叶子结点入队,从叶子结点往上模拟删去操作即可

#include <bits/stdc++.h> #define PII pair<int,int> #define x first #define y second using namespace std; const int N = 4e5 + 7; int n,k; int du[N]; bool vis[N]; void Init(){  for (int i=1;i<=n;i++) du[i] = 0; for (int i=1;i<=n;i++) vis[i] = 0; } int main(){  int t;cin>>t; while (t--){  cin>>n>>k; Init(); vector<int>v[n+1]; for (int i=0;i<n-1;i++){  int ui,vi;cin>>ui>>vi; du[ui]++,du[vi]++; v[ui].push_back(vi),v[vi].push_back(ui); } if (n==1){  cout<<0<<endl; continue; } queue<PII>q; //第一关键词存叶子结点 第二关键词存操作值 for (int i=1;i<=n;i++){  if (du[i]==1) q.push({ i,1}); }//将叶子结点入队 while (!q.empty()){  auto it = q.front(); q.pop(); if (vis[it.x]) continue; vis[it.x] = 1;//入队的叶子进行标记 for (auto i:v[it.x]){ //遍历和它连接的点  du[i]--;//该叶子删去所以du-- if (du[i]==1){ //度为1说明其变成新叶子 if (it.y+1<=k){ //当前操作值+1比k小 说明可以删去 q.push({ i,it.y+1}); } } } } int ans = 0; for (int i=1;i<=n;i++) if (!vis[i]) ans++; cout<<ans<<endl; } } 

其他题待补充