ACM题集:https://blog.csdn.net/weixin_39778570/article/details/83187443
题目链接:https://codeforces.com/contest/1111
A
元音之间可以互相转换,辅音之间可以互相转换,
若两个句子无法转换成同个句子输出No
否则输出Yes
#include<bits/stdc++.h>
#define ll long long
#define fo(i,j,n) for(register int i=j; i<=n; ++i)
using namespace std;
int a[1005],b[1005];
string s,t;
int main(){
cin>>s>>t;
if(s.length()!=t.length()){
cout<<"No";
}else{
for(int i=0; i<s.length(); i++){
if(s[i]=='a'||s[i]=='e'||s[i]=='i'||s[i]=='o'||s[i]=='o'||s[i]=='u'){
a[i] = 1;
}else a[i]=2;
if(t[i]=='a'||t[i]=='e'||t[i]=='i'||t[i]=='o'||t[i]=='o'||t[i]=='u'){
b[i] = 1;
}else b[i]=2;
if(a[i]!=b[i]){
cout<<"No";
return 0;
}
}
cout<<"Yes";
}
return 0;
}
B
现在有一个数列
你可以进行m次操作
操作1:删除一个数
操作2:对一个数加上1,一个数最大加k
现在问剩下的数列的平均值最大为多少
-------------------------------------
对数列排序好,然后我们尽可能删除掉小的数,并且加上所有能加的数
假设删了i个数,sum表示剩下的数的和
那么 avg = (sum + min(m-i,(n-i)*k) )/(n-i) 取其中最小的那一个
#include<bits/stdc++.h>
#define ll long long
#define fo(i,j,n) for(register int i=j; i<=n; ++i)
using namespace std;
ll n,k,m; //改int过不了,后面有用到
ll a[100100],sum;
signed main(){
cin>>n>>k>>m;
for(int i=1;i<=n;i++) scanf("%lld",a+i),sum+=a[i];
sort(a+1,a+1+n);
double avg = 1.0*(sum+min(m,n*k))/n; // 不删
for(int i=1; i<=min(n-1,m); i++){ // 删除i个小的
sum -= a[i];
avg = max(avg,1.0*(sum+min(m-i,(n-i)*k))/(n-i)); // 加上(n-i)*k全加满或全加完m-i
}
printf("%.15f",avg);
}
C
有个基地,长度为1-2^n,基地上有的有复仇者守着,有的没有
对一个基地你可以直接破坏掉他,也可以把他分成等长的两部分来破坏(长度大于等于2)
直接破坏:如果 L到R 号中的基地没有复仇者 破坏的代价为A
否则 代价 = B*na*len na表示有复仇者的基地的数量,len表是基地的长度
#include<bits/stdc++.h>
#define ll long long
#define fo(i,j,n) for(register int i=j; i<=n; ++i)
using namespace std;
ll n,k,A,B;
ll a[100005];
ll rec(ll l, ll r){
// 基地l到r种有复仇者的数量
ll na = upper_bound(a,a+k,r)-lower_bound(a,a+k,l);
ll destroyNow;
if(na==0){
destroyNow = A;
}else{
destroyNow = B * na * (r-l+1);
}
if(l==r || na==0)return destroyNow; // 无法分,或者找不到了(直接解决掉)
else{
ll mid = (l+r)>>1;
return min(destroyNow, rec(l,mid)+rec(mid+1,r));
}
}
int main(){
cin>>n>>k>>A>>B;
fo(i,0,k-1)scanf("%lld",&a[i]);
sort(a,a+k);
cout<<rec(1ll,1ll<<n);
return 0;
}