Codeforces Round #619 (Div. 2)
A. Three Strings
题意
给定abc三个字符串,c的每一位都必须与a或者b的对应位交换,问交换后的a和b是否可能相等
题解
由于c的每一位都必须交换,而交换后都要与另一个字符串的对应位比较,所以只需循环一遍,判断每一位c是否都能与a或者b对应位中的一个相等即可
代码
#include<iostream>
#include<cstdio>
using namespace std;
int main()
{ long N,i;
string a,b,c;
bool t;
scanf("%ld",&N);
while(N--){
cin>>a>>b>>c;
t=true;
for(i=0;i<a.length();i++)
if(c[i]!=a[i]&&c[i]!=b[i]){
t=false;
break;
}
if(t)
printf("YES\n");
else
printf("NO\n");
}
return 0;
}
B. Motarack’s Birthday
题意
给定一串数列,要求将其中的所有-1替换为同一个数k,求k使得替换后的整个数列相邻位之差的绝对值的最大值最小
题解
因为全部-1都替换为k,所以当-1两边的数与k的差值最小时,满足条件的k一定等于-1两边的(最大值+最小值)/2,替换后统计一遍即可
代码
#include<iostream>
#include<cstring>
#include<cstdio>
#define max(a,b) (((a)>(b))?(a):(b))
#define min(a,b) (((a)<(b))?(a):(b))
#define abs(i) (((i)>0)?(i):-(i))
#define def 100010
#define ll long long
using namespace std;
ll a[def];
int main()
{ ll N,n,i,num,ans,minn,maxx;
scanf("%lld",&N);
while(N--){
memset(a,0,sizeof(a));
scanf("%lld",&n);
for(i=1;i<=n;i++)
scanf("%lld",&a[i]);
minn=~(1<<31);
maxx=0;
for(i=1;i<=n;i++)
if(a[i]==-1){
if(i>1&&a[i-1]!=-1){
minn=min(minn,a[i-1]);
maxx=max(maxx,a[i-1]);
}
if(i<n&&a[i+1]!=-1){
minn=min(minn,a[i+1]);
maxx=max(maxx,a[i+1]);
}
}
num=(maxx+minn)/2;
for(i=1;i<=n;i++)
if(a[i]==-1)
a[i]=num;
ans=0;
for(i=1;i<n;i++)
ans=max(ans,abs(a[i+1]-a[i]));
if(minn!=~(1<<31))
printf("%lld %lld\n",ans,num);
else
printf("%lld %lld\n",ans,0ll);
}
return 0;
}
C. Ayoub’s function
题意
定义 f ( s ) f(s) f(s)为字符串s包含1的字串的个数,给定n和m,构造一个n位的01字符串,其中1的个数为m个,使得 f ( s ) f(s) f(s)最大
题解
用组合数可以推出,一个字符串的子串个数为
C
n
+
1
2
=
n
∗
(
n
+
1
)
/
2
C^2_{n+1}=n*(n+1)/2
Cn+12=n∗(n+1)/2
由于只含0的字串比含1的字串统计更方便,所以考虑0的摆放位置。问题转化为:一共
(
n
−
m
)
(n-m)
(n−m)个0,分成
m
+
1
m+1
m+1份,使每一份字串个数最少,剩下的1就放在产生的
m
m
m个空位里。
易证一个结论:
k
∗
(
k
+
1
)
/
2
∗
2
<
(
k
−
1
)
∗
k
/
2
+
(
k
+
1
)
∗
(
k
+
2
)
/
2
k*(k+1)/2*2<(k-1)*k/2+(k+1)*(k+2)/2
k∗(k+1)/2∗2<(k−1)∗k/2+(k+1)∗(k+2)/2
所以均分产生的字串数量最少,如果无法完全均分,就尽量均分。
最终答案就是:总子串数-所有只含0的字串数
代码
#include<cstdio>
#define ll long long
int main()
{ ll N,n,m,p,r;
scanf("%lld",&N);
while(N--){
scanf("%lld%lld",&n,&m);
p=(n-m)/(m+1);
r=(n-m)%(m+1);
printf("%lld\n",n*(n+1)/2-r*(p+1)*(p+2)/2-(m+1-r)*p*(p+1)/2);
}
return 0;
}