Educational Codeforces Round 108 (Rated for Div. 2) ABCD题解

A. Red and Blue Beans
思路:不妨假设r ,当b-r足够小时,一定是输出YES的。
只有当b-r 足够大时,才会无解。 极端情况就是 对于每一个口袋(packet) ,只放1个red bean 和d+1个blue bean,因此当r*(d+1) 代码:(注意相乘会爆int)

#include 
#include 
#include 
#include 
#include 
#include 
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 
#include 
#include 
#include 
#include 
#include 
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;
}

C. Berland Regional

思路:其实暴力就可以解决,给每个队的人按照能力排序(降序),然后记录前缀和。 枚举k,找到每只队伍大小距离k的倍数最近的值(例如队伍大小是 d 使得d-=d%k 即可,这样就满足了d是k的倍数),累加即可。 但是这样的复杂度是O(n^2) 容易超时,注意到当队伍大小d

#include 
#include 
#include 
#include 
#include 
#include 
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:"<
		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 
#include 
#include 
#include 
#include 
#include 
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 
#include 
#include 
#include 
#include 
#include 
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;
}

你可能感兴趣的:(codeforces,算法,动态规划,数据结构,leetcode,线性规划)