Educational Codeforces Round 108 (Rated for Div. 2) A-D题解
A.Red and Blue Beans
-
解题思路
此题要求我们分组,使得红豆和蓝豆的数量不得超过 d d d,也就是说一个红豆最多可以和 ( d + 1 ) (d+1) (d+1)个蓝豆组成一组,同理一个蓝豆也是一样的,所以我们只需要判断数量较小的那个豆能否最大的配凑使其组成一组,假设较小的为 a a a,较大的为 b b b,那么即是判断 a + a ∗ d a+a*d a+a∗d和 b b b的关系了。若大于等于,说明完全可以配成符合要求的组,否则不行。
-
代码
/**
*@filename:A_Red_and_Blue_Beans
*@author: pursuit
*@csdn:unique_pursuit
*@email: 2825841950@qq.com
*@created: 2021-04-29 22:35
**/
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 100000 + 5;
const int mod = 1e9+7;
ll t,r,b,d;
void solve(){
if(r<b)swap(r,b);
if(b+b*d>=r){
cout<<"YES"<<endl;
}
else{
cout<<"NO"<<endl;
}
}
int main(){
cin>>t;
while(t--){
cin>>r>>b>>d;
solve();
}
return 0;
}
B. The Cake Is a Lie
-
解题思路
这道题属实有点坑,只要动手去算,发现不管怎样出发,到达 ( n , m ) (n,m) (n,m)的消耗是一个定值,我们判断这个定值和 k k k是否相等即可。
-
代码
/**
*@filename:B_The_Cake_Is_a_Lie
*@author: pursuit
*@csdn:unique_pursuit
*@email: 2825841950@qq.com
*@created: 2021-04-29 22:42
**/
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 100000 + 5;
const int mod = 1e9+7;
int t,n,m,k;
void solve(){
if(k==(m-1)+m*(n-1)){
cout<<"YES"<<endl;
}
else{
cout<<"NO"<<endl;
}
}
int main(){
cin>>t;
while(t--){
cin>>n>>m>>k;
solve();
}
return 0;
}
C. Berland Regional
-
解题思路
我们对每个学校枚举 k k k, k k k实际上就是它们的最大成员数,那么为了凑成 k k k的倍数,我们需要除去余数即可。为了更高效的求和,我们可以利用前缀和。
-
代码
/**
*@filename:C_Berland_Regional
*@author: pursuit
*@csdn:unique_pursuit
*@email: 2825841950@qq.com
*@created: 2021-04-29 23:11
**/
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 200000 + 5;
const int mod = 1e9+7;
int t,n;//n为大学数量和学生数量。
vector<ll> g[maxn];//存储。
ll ans[maxn],u[maxn];
void solve(){
for(int i=1;i<=n;i++){
sort(g[i].begin(),g[i].end(),greater<int>() );
}
//前缀和。
for(int i=1;i<=n;i++){
for(int j=1;j<g[i].size();j++){
g[i][j]+=g[i][j-1];//前缀和
}
}
//对每个学校枚举k,k即为它们的最大成员数。
for(int i=1;i<=n;i++){
int k=g[i].size();
for(int j=1;j<=k;j++){
ans[j]+=g[i][k-k%j-1];//除去余数。
}
}
for(int i=1;i<=n;i++){
cout<<ans[i];
i==n?cout<<endl:cout<<" ";
}
}
int main(){
cin>>t;
while(t--){
cin>>n;
int temp;
for(int i=1;i<=n;i++){
cin>>u[i];
g[i].clear();
ans[i]=0;
}
for(int i=1;i<=n;i++){
cin>>temp;
g[u[i]].push_back(temp);
}
solve();
}
return 0;
}
D. Maximum Sum of Products
-
解题思路
一道区间 d p dp dp问题,我们先定义状态: d p [ l ] [ r ] dp[l][r] dp[l][r]即表示的是翻转区间 [ l , r ] [l,r] [l,r]之后这段区间 ∑ i = l r a i × b i \sum_{i=l}^ra_i\times b_i ∑i=lrai×bi的最大值。那么为了方便,我们每次递推翻转左右端点即可,故状态转移方程即为 d [ i ] [ j ] = d p [ i + 1 ] [ j − 1 ] + a [ i ] ∗ b [ j ] + a [ j ] ∗ b [ i ] d[i][j]=dp[i+1][j-1]+a[i]*b[j]+a[j]*b[i] d[i][j]=dp[i+1][j−1]+a[i]∗b[j]+a[j]∗b[i], 处理完之后,最后需要枚举一遍区间取最大值。需要注意的是,我们枚举左端点的时候要从大到小,因为右端点 j j j会用到 i + 1 i+1 i+1。
-
代码
/**
*@filename:D_Maximum_Sum_of_Products
*@author: pursuit
*@csdn:unique_pursuit
*@email: 2825841950@qq.com
*@created: 2021-04-30 10:34
**/
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 5000 + 5;
const int mod = 1e9+7;
int n;
ll a[maxn],b[maxn],dp[maxn][maxn],s[maxn];//区间dp。dp[l][r]即表示的是翻转区间[l,r]之后这段区间ai*bi的最大值。
//则易知状态转移方程为d[i][j]=dp[i+1][j-1]+a[i]*b[j]+a[j]*b[i];
void solve(){
}
int main(){
cin>>n;
for(int i=1;i<=n;i++)cin>>a[i];
for(int i=1;i<=n;i++)cin>>b[i];
for(int i=1;i<=n;i++){
s[i]=s[i-1]+a[i]*b[i];//记录前缀和,便于之后操作。
}
//初始化,只翻转一个数的时候,即等于没有翻转。
for(int i=1;i<=n;i++){
dp[i][i]=a[i]*b[i];
}
//枚举左右端点。
for(int i=n-1;i>=1;i--){
for(int j=i+1;j<=n;j++){
//注意这里的i必须是从大到小,因为我们的j会用到i+1。
dp[i][j]=max(dp[i][j],dp[i+1][j-1]+a[i]*b[j]+a[j]*b[i]);
}
}
//所有状态更新完之后开始取max。
ll ans=s[n];
for(int i=1;i<=n;i++){
for(int j=i+1;j<=n;j++){
ans=max(ans,dp[i][j]+s[i-1]+s[n]-s[j]);
}
}
cout<<ans<<endl;
solve();
return 0;
}
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek “源神”启动!「GitHub 热点速览」
· 我与微信审核的“相爱相杀”看个人小程序副业
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 如何使用 Uni-app 实现视频聊天(源码,支持安卓、iOS)
· C# 集成 DeepSeek 模型实现 AI 私有化(本地部署与 API 调用教程)