AtCoder Beginner Contest 155 题解

传送门:这里

这场好难,枯了。

A

分类讨论

#include<bits/stdc++.h>
using namespace std;

int main(){
	int a[3];
	for(int i=0; i<3; i++) cin>>a[i];
	sort(a, a+3);
	
	if(a[0]==a[1] && a[1]!=a[2] || a[0]!=a[1] && a[1]==a[2]) puts("Yes");
	else puts("No");
	return 0;
}

B

模拟

#include<bits/stdc++.h>
using namespace std;

int main(){
	int n; cin>>n;
	
	bool ok=true;
	while(n--){
		int t; cin>>t;
		if(t%2==0){
			if(t%3!=0 && t%5!=0) ok=false;
		}
	}
	puts(ok? "APPROVED": "DENIED");
	return 0;
}

C

模拟

#include<bits/stdc++.h>
using namespace std;

map<string, int> mp;

int main(){
	int n; cin>>n;
	while(n--){
		string t; cin>>t;
		mp[t]++;
	}
	
	int num=0;
	for(auto i: mp) num=max(num, i.second);
	
	for(auto i: mp) if(i.second==num) cout<<i.first<<endl;
	return 0;
}

D

二分答案,看看二分出来的 \(v\) 在所有数中的排名。麻烦在于求排名的时候也要二分 qwq

#pragma GCC optimize("O3")
#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
#define debug(x) cerr << #x << ": " << x << endl
#define pb(a) push_back(a)
#define set0(a) memset(a,0,sizeof(a))
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define dwn(i,a,b) for(int i=(a);i>=(b);i--)
#define ceil(a,b) (a+(b-1))/b
#define INF 0x3f3f3f3f
#define ll_INF 0x7f7f7f7f7f7f7f7f
typedef long long ll;
typedef pair<int,int> PII;
typedef pair<double,double> PDD;

#define int long long

inline void read(int &x) {
    int s=0;x=1;
    char ch=getchar();
    while(ch<'0'||ch>'9') {if(ch=='-')x=-1;ch=getchar();}
    while(ch>='0'&&ch<='9') s=(s<<3)+(s<<1)+ch-'0',ch=getchar();
    x*=s;
}

const int N=2e5+5;

int n, k;
int w[N];

int get_rank(int v){
	int rk=0;
	rep(i,1,n-1){
		int cur=w[i];
		if(cur<0){
			int L=i+1, R=n;
			while(L<R){
				int mid=L+R>>1;
				if(v>cur*w[mid]) R=mid;
				else L=mid+1; 
			}
			if(v>cur*w[L]) rk+=n-L+1;
		}
		else{
			int L=i+1, R=n;
			while(L<R){
				int mid=L+R+1>>1;
				if(v>cur*w[mid]) L=mid;
				else R=mid-1;
			}
			if(v>cur*w[L]) rk+=L-i;
		}
	}
	rk++;
	// debug(rk);
	return rk;
}

signed main(){
	read(n), read(k);
	rep(i,1,n) read(w[i]);
	sort(w+1, w+1+n);
	
	int l=-1e18, r=1e18;
	while(l<r){
		int mid=l+r+1>>1;
		if(get_rank(mid)<=k) l=mid;
		else r=mid-1;
	}
	cout<<l<<endl;
	
    return 0;
}

E

分析

我们采取 dp 的做法。

为了直观地考虑这个问题,我们将原串用 \(a\) 表示,根据题意,我们的目标是最小化 \(\sum (b_i+c_i)\) (求最小代价)。

\(\begin {array}{ccc} &a_n&a_{n-1}&...&a_1\\ +&b_n&b_{n-1}&...&b_1\\ \hline =&c_n&c_{n-1}&...&c_1 \end {array}\)

不失一般性,考察第 \(i\) 位,分成两种情况讨论:

  • 第 \(i\) 位发生进位。

  • 第 \(i\) 位不发生进位。

对于第一种情况:
我们有 \(a_i + b_i = 10 + c_i\) (因为发生了进位),要最小化 \(b_i + c_i\) ,

因为 \(b_i + c_i = 2b_i + a_i - 10\) ,我们只需要最小化 \(b_i\) ,故让 \(b_i = 10 - a_i\) 即可,相应地,可得 \(c_i = 0\)

类似地,在第二种情况中可得相应的 \(b_i = 0,~ c_i = a_i\)

下面开始 dp:\(f[i][0/1]\) 表示第 \(i\) 位不进位 / 进位下前 \(i\) 位的最小代价。

如果第 \(i-1\) 位没有发生进位,那么第 \(i\) 位没有受到影响,直接针对上面的讨论进行转移即可。

如果发生进位,那么第 \(i\) 位的 \(a_i\) 相当于 \(a_i+1\) 类似地进行转移。

结合转移方程理解:

\[f[i][0]=min(f[i-1][0]+a[i], ~f[i-1][1]+a[i]+1) \]

\[f[i][1]=min(f[i-1][0]+10-a[i],~ f[i-1][1]+10-1-a[i]); \]

代码:

#pragma GCC optimize("O3")
#include<bits/stdc++.h>
using namespace std;

#define rep(i,a,b) for(int i=(a);i<=(b);i++)

int t(char ch){ // char 转 int
	return ch-'0';
}

const int N=1e6+5;

int f[N][2];

int main(){
	string s; cin>>s; int n=s.size(); reverse(s.begin(), s.end()); s=' '+s;
	
	f[0][1]=1, f[0][0]=0;
	rep(i,1,n){
		f[i][0]=min(f[i-1][0]+t(s[i]), f[i-1][1]+t(s[i])+1);
		f[i][1]=min(f[i-1][0]+10-t(s[i]), f[i-1][1]+10-1-t(s[i]));
	}
	cout<<min(f[n][1]+1, f[n][0]);
	
    return 0;
}
上一篇:spfa判负环(01分数规划)


下一篇:(int argc, char *argv[])在MCU中的调试使用