Educational Codeforces Round 108 (Rated for Div. 2) ABCD题解
Posted 桂月二四
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Educational Codeforces Round 108 (Rated for Div. 2) ABCD题解相关的知识,希望对你有一定的参考价值。
A. Red and Blue Beans
思路:不妨假设r<b ,当b-r足够小时,一定是输出YES的。
只有当b-r 足够大时,才会无解。 极端情况就是 对于每一个口袋(packet) ,只放1个red bean 和d+1个blue bean,因此当r*(d+1)<b时无解。
代码:(注意相乘会爆int)
#include <iostream>
#include <cmath>
#include <map>
#include <cstring>
#include <vector>
#include <algorithm>
using namespace std;
typedef long long ll;
const int N = 10010;
int a[N];
int main()
int T;cin>>T;
ll n;
ll r,b,d;
while(T--)
cin>>r>>b>>d;
ll mi = min(r,b),ma = max(r,b);
if(mi*(d+1)<ma) puts("NO");
else puts("YES");
return 0;
B. The Cake Is a Lie
观察知,无论怎么走,从(1,1) 到(n,m) 所需的花费相同。
代码:
#include <iostream>
#include <cmath>
#include <map>
#include <cstring>
#include <vector>
#include <algorithm>
using namespace std;
typedef long long ll;
const int N = 10010;
int a[N];
int main()
int T;cin>>T;
ll n,m,k;
ll d;
while(T--)
cin>>n>>m>>k;
d = n-1+(m-1)*n;
if(d==k)
puts("YES");
else puts("NO");
return 0;
思路:其实暴力就可以解决,给每个队的人按照能力排序(降序),然后记录前缀和。 枚举k,找到每只队伍大小距离k的倍数最近的值(例如队伍大小是 d 使得d-=d%k 即可,这样就满足了d是k的倍数),累加即可。 但是这样的复杂度是O(n^2) 容易超时,注意到当队伍大小d<k时就退出,因此我们可以对队伍大小进行排序(用pair记录队伍人数和队伍号) ,对队伍人数降序排列。当d<k时直接break即可
#include <iostream>
#include <cmath>
#include <map>
#include <cstring>
#include <vector>
#include <algorithm>
using namespace std;
typedef long long ll;
const int N = 200010;
typedef pair<int,int> PII;
struct stu
int u,s;
a[N];
vector<ll> re[N];
PII op[N];
int cnt[N];
int cmp(int a,int b)
return a>b;
int main()
int T;cin>>T;
int n,m,k;
ll d;
while(T--)
ll res = 0;
scanf("%d",&n);
memset(cnt,0,sizeof cnt);
memset(op,0,sizeof op);
for(int i=1;i<=n;i++)
scanf("%d",&a[i].u);
re[i].clear();
cnt[a[i].u]++;
int now = 0;
for(int i=1;i<=n;i++)
if(cnt[i]) op[++now] = cnt[i],i;
sort(op+1,op+1+now);
reverse(op+1,op+1+now);
for(int i=1;i<=n;i++)
scanf("%d",&a[i].s);
for(int i=1;i<=n;i++)
re[a[i].u].push_back(a[i].s);
for(int i=1;i<=n;i++)
sort(re[i].begin(),re[i].end(),cmp);
for(int i=1;i<=n;i++)
int t = re[i].size();
for(int j=1;j<t;j++)
re[i][j] = re[i][j-1]+re[i][j];
//cout<<"de:"<<sum[1][2]<<endl;
for(int k=1;k<=n;k++)
ll res = 0;
for(int s=1;s<=now;s++)
int i = op[s].second;
int t = re[i].size();
if(t<k) break;
t-=t%k;
res+=re[i][t-1];
printf("%lld ",res);
puts("");
return 0;
D. Maximum Sum of Products
裸裸的区间dp,假设f[l][r] 代表反转l~r之间的值所形成的值 则有f[l][r] = f[l+1][r-1] - a[l]*b[l] - a[r]*b[r] + a[l]*b[r] + a[r]*b[l]
代码
#include <iostream>
#include <cmath>
#include <map>
#include <cstring>
#include <vector>
#include <algorithm>
using namespace std;
typedef long long ll;
const int N = 5010;
ll a[N],b[N];
ll f[N][N];
int main()
int n;cin>>n;
ll res = 0;
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
for(int i=1;i<=n;i++)
scanf("%d",&b[i]),res+=a[i]*b[i];
for(int i=1;i<=n;i++)
f[i][i] = f[i][i-1] = res;
int r;
for(int len = 2;len<=n;len++)
for(int l = 1;l+len-1<=n;l++)
r = l+len-1;
f[l][r] = f[l+1][r-1] - a[l]*b[l] - a[r]*b[r] + a[l]*b[r] + a[r]*b[l];
res = max(res,f[l][r]);
cout<<res;
return 0;
记忆化搜索写法
#include <iostream>
#include <cmath>
#include <map>
#include <cstring>
#include <vector>
#include <algorithm>
using namespace std;
typedef long long ll;
const int N = 5010;
ll a[N],b[N];
ll f[N][N];
ll d;
ll dp(int l,int r)
if(f[l][r]) return f[l][r];
return f[l][r] = dp(l+1,r-1) - a[l]*b[l] - a[r]*b[r] + a[l]*b[r] + a[r]*b[l];
int main()
int n;cin>>n;
ll res = 0;
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
for(int i=1;i<=n;i++)
scanf("%d",&b[i]),res += a[i]*b[i];
for(int i=1;i<=n;i++)
f[i][i] = f[i][i-1] = res;
for(int i=1;i<=n;i++)
for(int j=i+1;j<=n;j++)
res = max(res,dp(i,j));
cout<<res;
return 0;
以上是关于Educational Codeforces Round 108 (Rated for Div. 2) ABCD题解的主要内容,如果未能解决你的问题,请参考以下文章
Educational Codeforces Round 7 A
Educational Codeforces Round 7
Educational Codeforces Round 90
Educational Codeforces Round 33