Educational Codeforces Round 88 (Div. 2) 题解 (ABCDE)

https://codeforces.com/contest/1359

A. Berland Poker

大概就是把jokers尽可能多地给一个人,其他人平均分吧

#include <bits/stdc++.h>
using namespace std;
#define repeat(i,a,b) for(int i=(a),_=(b);i<_;i++)
#define repeat_back(i,a,b) for(int i=(b)-1,_=(a);i>=_;i--)
int cansel_sync=(ios::sync_with_stdio(0),cin.tie(0),0);
const int N=200010; typedef long long ll;
#define int ll
int T,n,m,k;
signed main(){
	cin>>T;
	while(T--){
		cin>>n>>m>>k;
		if(n/k>=m)cout<<m<<endl;
		else{
			int t=(m-n/k+k-1-1)/(k-1);
			cout<<n/k-t<<endl;
		}
	}
	return 0;
}

B. New Theatre Square

没什么好说的,就模拟

#include <bits/stdc++.h>
using namespace std;
#define repeat(i,a,b) for(int i=(a),_=(b);i<_;i++)
#define repeat_back(i,a,b) for(int i=(b)-1,_=(a);i>=_;i--)
int cansel_sync=(ios::sync_with_stdio(0),cin.tie(0),0);
const int N=200010; typedef long long ll;
#define int ll
int T,n,m,a,b;
string s;
signed main(){
	cin>>T;
	while(T--){
		cin>>n>>m>>a>>b; b=min(b,2*a);
		int ans=0;
		repeat(i,0,n){
			cin>>s;
			repeat(j,0,m)
			if(s[j]=='.'){
				if(j!=m-1 && s[j+1]=='.'){
					s[j+1]='*';
					ans+=b;
				}
				else ans+=a;
			}
		}
		cout<<ans<<endl;
	}
	return 0;
}

C. Mixing Water

哭哭~,写得我整个人都不好了,最后还是放弃(赛后,double改成long double交了一下过了。。但是不保证不会fst,就先放这吧)

初步分析,如果t比较小那就直接输出2,否则就是一个奇数,比较麻烦。如果不断+2来找答案就超时了(TLE test4),因此我直接考虑推柿子

当然也可以二分答案(%%%猛男lzj提供的思路)

我的解法:

#include <bits/stdc++.h>
using namespace std;
#define repeat(i,a,b) for(int i=(a),_=(b);i<_;i++)
#define repeat_back(i,a,b) for(int i=(b)-1,_=(a);i>=_;i--)
int cansel_sync=(ios::sync_with_stdio(0),cin.tie(0),0);
const int N=200010; typedef long long ll;
#define int ll
typedef long double lf;
int T,h,c,t;
signed main(){
	cin>>T;
	while(T--){
		cin>>h>>c>>t;
		if(t<=(h+c)/2){cout<<2<<endl; continue;}
		lf t2=(t-lf(h+c)/2)/(h-c);
		lf t3=floor(1/(4*t2)-0.5);
		int x=llround(t3),y=x+1;
		if(abs(lf(1)/(4*x+2)-t2)<=abs(lf(1)/(4*y+2)-t2))
			cout<<x*2+1<<endl;
		else
			cout<<y*2+1<<endl;
	}
	return 0;
}

D. Yet Another Yet Another Task

先固定最大值,如果最大值固定(设它为 (k))那么这时候的答案就是(去掉比最大值大的数后的)最大连续子序列和减去 (k),即 (maxlimits_{(l,r)}sumlimits_{i=l}^r a[i]-k),非常好求

所以只要for k=30 downto -30就行了,然后里面for一遍就行了

更加猛的方法是,每次插入未插入的最小的 (a_i),线段树维护最大子序列和(考虑到有些读者没接触过就讲一下,线段树的每个节点存三个值,答案、可以向左延伸的答案、可以向右延伸的答案(区间和可能也要))当然了,这种方法在 (a_i) 范围很大的时候也适用

#include <bits/stdc++.h>
using namespace std;
#define repeat(i,a,b) for(int i=(a),_=(b);i<_;i++)
#define repeat_back(i,a,b) for(int i=(b)-1,_=(a);i>=_;i--)
int cansel_sync=(ios::sync_with_stdio(0),cin.tie(0),0);
const int N=200010; typedef long long ll;
#define int ll
int n,a[N];
signed main(){
	cin>>n;
	repeat(i,0,n)cin>>a[i];
	int ans=0;
	repeat_back(k,-30,30+1){
		int now=-1e9;
		repeat(i,0,n){
			if(now<0)now=a[i];
			else now+=a[i];
			ans=max(ans,now-k);
		}
		repeat(i,0,n)if(a[i]==k)a[i]=-1e9;
	}
	cout<<ans<<endl;
	return 0;
}

E. Modular Stability

搞了一会儿发现隐藏大结论,所有 (a_i) 必须能被最小值 (a_1) 整除。为什么呢?因为。。啊没想明白,不会证(更:取一个不能被 (a_1) 整除的 (a_t),再取 (x=a_t),显然 (x\%a_1\%a_t ot=0,x\%a_t\%a_1=0),证毕)

这样的话,只要枚举 (a_1) 的值,然后计算组合数就行了。发现结论后剩下的步骤挺水的

#include <bits/stdc++.h>
using namespace std;
#define repeat(i,a,b) for(int i=(a),_=(b);i<_;i++)
#define repeat_back(i,a,b) for(int i=(b)-1,_=(a);i>=_;i--)
int cansel_sync=(ios::sync_with_stdio(0),cin.tie(0),0);
const int N=200010; typedef long long ll;
const int mod=(0?1000000007:998244353); ll mul(ll a,ll b,ll m=mod){return a*b%m;} ll qpow(ll a,ll b,ll m=mod){ll ans=1; for(;b;a=mul(a,a,m),b>>=1)if(b&1)ans=mul(ans,a,m); return ans;} ll getinv(ll v,ll m=mod){return qpow(v,m-2,m);}
#define int ll
int n,k;
struct CC{
	static const int N=500010;
	ll fac[N],inv[N];
	CC(){
		fac[0]=1;
		repeat(i,1,N)fac[i]=fac[i-1]*i%mod;
		inv[N-1]=qpow(fac[N-1],mod-2,mod);
		repeat_back(i,0,N-1)inv[i]=inv[i+1]*(i+1)%mod;
	}
	ll operator()(ll a,ll b){ //a>=b
		if(a<b)return 0;
		return fac[a]*inv[a-b]%mod*inv[b]%mod;
	}
}C;
signed main(){
	cin>>n>>k; int ans=0;
	repeat(i,1,n+1){
		(ans+=C(n/i-1,k-1))%=mod;
	}
	cout<<ans<<endl;
	return 0;
}
原文地址:https://www.cnblogs.com/axiomofchoice/p/12985014.html