(Training 11)Codeforces Round #691

A. Red-Blue Shuffle

只要看谁大的数量多即可

#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=1e6+10;
int a[N],b[N];
int main(){
	int T;
	scanf("%d",&T);
	while(T--){
		int n;
		scanf("%d",&n);
		string a,b;
		cin>>a>>b;
		int red=0,bule=0;
		for(int i=0;i<n;i++){
			if(a[i]>b[i])red++;
			else if(b[i]>a[i])bule++;
		}
		if(red>bule)puts("RED");
		else if(bule>red)puts("BLUE");
		else puts("EQUAL");
	}
}

B. Move and Turn

思路: 我们分别观察在某步时可达的x和y
如果现在是第n步 且n偶数 因为每次走了横纵标后一定要走纵坐标 所以 令k=n/2 而我们可以到达的横坐标只能为 -k -k+2 -k+4 …k 可以知道能到的坐标数量为k+1 反观纵坐标依然如此 通过乘法原则 方案数为(k+1)(k+1)
当步数为奇数时 如果 横坐标少走一次依然设 k=n/2 那么他为k+1 而纵坐标的方案就变味了n-k+1 因为横坐标和纵坐标可以交换 那么ans = (k+1)
(n-k+1)*2
后续把k替换即可


#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=1e6+10;
typedef long long LL;
int main(){
	LL n;
	cin>>n;
	if(n&1)cout<<(n/2+1)*(n-n/2+1)*2;
	else cout<<(n/2+1)*(n/2+1);
    return 0;
}

C - Row GCD

思路:写过线段树维护区间GCD的同学应该能很快写出来
而这里是对整个区间 那么我们直接用差分数组
来求解整个的GCD
如果要对整个数组加上d只需要对数组开头加上d即可
再来重新求得GCD等于多少

#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=1e6+10;
typedef long long LL;
LL a[N],b[N];
LL Gcd(LL x,LL y){
	return y?Gcd(y,x%y):x;
}
int main(){
	int n,m;
	cin>>n>>m;
	for(int i=1;i<=n;i++){
		scanf("%lld",&a[i]);
	}
	LL gcd=a[2];
	for(int i=3;i<=n;i++){
		gcd=Gcd(gcd,a[i]-a[i-1]);//差分 
	}
	for(int j=1;j<=m;j++){
		LL x;
		scanf("%lld",&x);
		printf("%lld ",abs(Gcd(a[1]+x,gcd)));
	}
 
}

D. Glass Half Spilled

思路:没想到居然是个二维的背包问题
dp i j k表示前i个杯子选择 j个 剩余k体积时的最大含水量
这里我们要用滚动数组
随后没有被选的被子的含水量就是总水量 sum-dp[j][k]
而选择i个时最大值就为 min(j*1.0,(sum-f[i][j])/2.0)+f[i][j]

#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long LL;
int f[105][10005];
double ans[105];
int a[105],b[105];
int main(){
	int n;
	scanf("%d",&n);
	int sum=0;
	for(int i=1;i<=n;i++){
		scanf("%d%d",&a[i],&b[i]);
		sum+=b[i];
	}
	memset(f,0xcf,sizeof f);
	for(int i=0;i<=n;i++)
	f[i][0]=0;
	for(int i=1;i<=n;i++)//前i个杯子
		for(int j=i;j>=1;j--)//选择j个
		 	for(int k=100*j;k>=a[i]-b[i];k--)//滚动数组枚举选下i的剩余容量 
		 	f[j][k]=max(f[j][k],f[j-1][k-a[i]+b[i]]+b[i]);//选i的情况下的最大的b的总和  
	for(int i=1;i<=n;i++)
		for(int j=0;j<=100*i;j++){
			ans[i]=max(ans[i],f[i][j]+min(j*1.0,(sum-f[i][j])/2.0));
		}
		
	for(int i=1;i<=n;i++)
		printf("%.10lf ",ans[i]);
}
已标记关键词 清除标记
相关推荐
©️2020 CSDN 皮肤主题: 1024 设计师:白松林 返回首页