Codeforces Round 973 (Div. 2)
C:
因为不会打暴力算复杂度所以没过。其实根本不需要技巧直接先往右问再往左问就是2n的
#include<iostream>
using namespace std;
const int mod = 998244353;
int que(string s){
cout<<"? "<<s<<endl;
int x;cin>>x;return x;
}
int main(){
int t;cin>>t;while(t--){
int n;cin>>n;
string s="1";
if(que(s)){
int nw=0;
while(s.size()<n){
string tmp;
if(!nw){
tmp=s+'0';
if(que(tmp))s=tmp;
else nw=1;
}
else{
tmp=s+'1';
if(que(tmp))s=tmp,nw=0;
else break;
}
}
nw=0;
while(s.size()<n){
string tmp;
tmp='0'+s;
if(que(tmp))s=tmp;
else s='1'+s;
}
cout<<'!'<<' '<<s<<endl;
}
else{
cout<<"! ";
for(int i=1;i<=n;i++)cout<<0;
cout<<endl;
}
}
}
D:
一眼二分,熟悉的味道
有O(logn)和O(n)两种做法。
logn就是二分最大最小,就不细说了。
O(n)是要想一下结论的。
wa了一发主要是没看数据范围习惯性开max为0x3f3f3f3f.
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int mod = 998244353,maxn=2e5+10;
int a[maxn],pre[maxn],f[maxn];
int cl(int a,int b){
return (a+b-1)/b;
}
signed main(){
int t;cin>>t;while(t--){
int n;cin>>n;
for(int i=1;i<=n;i++)cin>>a[i],pre[i]=pre[i-1]+a[i];
int sum=0,mn=1e17,mx=0;
for(int i=1;i<=n;i++)mn=min(mn,pre[i]/i),f[i]=mn;
for(int i=n;i>=1;i--){
sum+=a[i];
mx=max(mx,cl(sum,n-i+1));
}
cout<<mx-mn<<endl;
}
}
E:
思考的是贪心找最小,二十次以内即可找到最小的gcd,之后随便递推即可
贪心证明待补充。
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int mod = 998244353,maxn=2e5+10;
int a[maxn];
signed main(){
int t;cin>>t;while(t--){
int n;cin>>n;
for(int i=1;i<=n;i++)cin>>a[i];
sort(a,a+n+1);
int ans=a[1],gcd=a[1];
int tt=min(n-1,1ll*20);
while(tt--){
int biao=0,mn=gcd;
for(int i=2;i<=n;i++){
//cout<<a[i]<<"mk"<<endl;
if(a[i]==-1)continue;
if(__gcd(gcd,a[i])<=mn)biao=i,mn=__gcd(gcd,a[i]);
}
//cout<<gcd<<' '<<biao<<endl;
gcd=mn;
a[biao]=-1;ans+=gcd;
}
if(n>21){
for(int i=2;i<=n;i++){
if(a[i]==-1)continue;
gcd=__gcd(gcd,a[1]);
ans+=gcd;
}
}
cout<<ans<<endl;
}
}

浙公网安备 33010602011771号