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]);
}