Educational Codeforces Round 20解(bu)题记录

Posted vainglory

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Educational Codeforces Round 20解(bu)题记录相关的知识,希望对你有一定的参考价值。

A. Maximal Binary Matrix

解法:暴力模拟+贪心

技术分享图片
#include<bits/stdc++.h>
using namespace std;
int a[110][110];
int main(){
    int n,k,cmp,f=0;scanf("%d%d",&n,&k);
    if(k>n*n){puts("-1");return 0;}cmp=n;
    int r=1;
    while(k>=2*cmp-1){
        k-=2*cmp-1;cmp-=1;
        for(int i=1;i<=n;i++) a[r][i]=a[i][r]=1;
        r++;
        if(k==0) break;
    }
    if(k==0){
        for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            cout<<a[i][j]<<" ";
        }
        cout<<endl;
        }
        return 0;
    }
    if(k&1){
        a[r][r]=1;k-=1;
        k/=2;
        for(int i=r+1;i<=r+k;i++) a[r][i]=a[i][r]=1;
    }
    else{
        a[r+1][r+1]=a[r][r]=1;k-=2;k/=2;
        for(int i=r+1;i<=r+k;i++) a[r][i]=a[i][r]=1;
    }
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            cout<<a[i][j]<<" ";
        }
        cout<<endl;
    }
    return 0;
}
View Code

B. Distances to Zero

解法:正着扫一遍,倒着扫一遍记录答案就好

技术分享图片
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+10;
int a[N],ans[N];
set<int>se;
int main(){
    int n;scanf("%d",&n);se.insert(1e8);
    for(int i=1;i<=n;i++) {scanf("%d",&a[i]);ans[i]=1e8;}
    int tmp=-1;
    for(int i=1;i<=n;i++){
        if(a[i]==0) tmp=i,ans[i]=0;
        else{
            if(tmp!=-1) ans[i]=i-tmp;
        }
    }
    tmp=-1;
    for(int i=n;i>=1;i--){
        if(a[i]==0) tmp=i,ans[i]=0;
        else{
            if(tmp!=-1) ans[i]=min(ans[i],tmp-i);
        }
    }
    for(int i=1;i<=n;i++) printf("%d ",ans[i]);
    return 0;
}
View Code

C. Maximal GCD

题意:构造n个数,使得他们的和为一个数,且gcd最大

解法:sqrt(n)处理最大gcd,构造 gcd*(1+2+...+n-1+k)   k=sum/gcd-(n-1)*n/2;

技术分享图片
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll n,k;
ll max_(ll a,ll b) {return a>b?a:b;}
int main(){
    scanf("%I64d%I64d",&n,&k);
    if(k>=1e6){puts("-1");return 0;}
    int ans=-1;ll cmp=k*(k+1)/2;
    for(ll i=1;i*i<=n;i++){
        if(n%i) continue;
        if(n/i>=cmp) ans=max_(ans,i);
        if(i>=cmp) ans=max_(ans,n/i);
    }
    if(ans==-1){puts("-1");return 0;}
    ll cnt=n/ans;
    for(ll i=1;i<k;i++){
        printf("%I64d ",i*ans);
        cnt-=i;
    }
    printf("%I64d
",cnt*ans);
    return 0;
}
View Code

D. Magazine Ad

解法:答案具有单调性,二分答案即可

技术分享图片
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+10;
char s[N];int a[N];int k,cnt;
bool ok(int x){
    int sum=0,res=0; 
    for(int i=0;i<=cnt;i++){
        sum+=a[i];
        if(a[i]>x) return 0;
        if(sum>x){res++;sum=a[i];}
    } 
    if(sum) res++;
    if(res>k) return 0; 
    return 1;
}
int main(){
    scanf("%d",&k);getchar();gets(s);int p=0; 
    for(int i=1;s[i];i++){
        if(s[i]== ||s[i]==-) a[cnt++]=(i-p+1),p=i+1; 
    }
    a[cnt]=strlen(s)-p;
    int l=1,r=N;int mid,ans=N;
    while(l<=r){
        mid=(l+r)>>1;
        //cout<<l<<" "<<r<<" "<<ans<<endl;
        if(ok(mid)) ans=min(ans,mid),r=mid-1;
        else l=mid+1; 
    }
    printf("%d
",ans);
    return 0;
}
View Code

E. Roma and Poker

解法:考虑n^2的dp,dp[n][k]代表胜积分为k是否可行,然后最后dfs记录答案即可

技术分享图片
#include<bits/stdc++.h>
using namespace std;
const int N=1100;
bool dp[N][2*N];
char ans[N];int n,k;string s;
void dfs(int x,int k){
    //cout<<x<<" "<<k<<endl;
    if(x==0) return;
    if(s[x]==L&&dp[x-1][k-1]) dfs(x-1,k-1);
    else if(s[x]==W&&dp[x-1][k+1]) dfs(x-1,k+1);
    else if(s[x]==D&&dp[x-1][k]) dfs(x-1,k);
    else{
        if(dp[x-1][k-1]) ans[x]=L,dfs(x-1,k-1);
        else if(dp[x-1][k+1]) ans[x]=W,dfs(x-1,k+1);
        else if(dp[x-1][k]) ans[x]=D,dfs(x-1,k);
    }
}
int main(){
    std::ios::sync_with_stdio(false);
    cin>>n>>k>>s;s=0+s;dp[0][k+1]=1;
    //k+1 ????0
    //1 ????-k
    //2*k+1 ????k 
    for(int i=1;i<=n;i++){
        for(int j=1;j<=2*k+1;j++){
            if(s[i]==L) dp[i][j]=dp[i-1][j-1];
            else if(s[i]==W) dp[i][j]=dp[i-1][j+1];
            else if(s[i]==D) dp[i][j]=dp[i-1][j];
            else dp[i][j]=max({dp[i-1][j+1],dp[i-1][j-1],dp[i-1][j]});
            if(i!=n) dp[i][1]=0,dp[i][2*k+1]=0;
        }
    }
    if(!dp[n][2*k+1]&&!dp[n][1]) {puts("NO");return 0;}
    if(dp[n][2*k+1]){dfs(n,2*k+1);}
    else dfs(n,1);
    for(int i=1;i<=n;i++) if(s[i]!=?) ans[i]=s[i];
    for(int i=1;i<=n;i++) printf("%c",ans[i]);printf("
");
    return 0;
}
View Code

F. Coprime Subsequences

题意:对于给定的序列,问有多少子序列的gcd为1

解法:考虑到题目的范围,即1e5的范围内约数大约有200,1e9的范围约数大约有800个,然后枚举gcd,从总答案里面减去就好,因为约数有容斥的地方,所以考虑用莫比乌斯反演,应用答案约数之间的关系可求解

技术分享图片
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+10;
int mbs[N],vis[N],p[N];
const int mod=1e9+7;
ll pow_(int a,int b){
    ll res=1,tmp=a;
    while(b){
        if(b&1) (res*=tmp)%=mod;
        b/=2;
        (tmp*=tmp)%=mod;
    }
    return res;
}
void mobius(){
    mbs[1]=1;int cnt=0;
    for(int i=2;i<N;i++){
        if(!vis[i]) p[++cnt]=i,mbs[i]=-1;
        for(int j=1;j<=cnt&&i*p[j]<N;j++){
            vis[i*p[j]]=1;
            if(i%p[j]==0) {mbs[i*p[j]]=0;break;}
            mbs[i*p[j]]=-mbs[i];
        }
    }
}
int cnt[N],a[N];
int main(){
    int n;scanf("%d",&n);mobius();int m=0;
    for(int i=1;i<=n;i++) scanf("%d",&a[i]),m=max(m,a[i]);
    for(int i=1;i<=n;i++){
        for(int j=1;j*j<=a[i];j++){
            if(a[i]%j==0){cnt[j]++;if(a[i]!=j*j) cnt[a[i]/j]++;}
        }
    }
    ll ans=0;
    for(int i=1;i<=m;i++){
        ll tmp=((pow_(2,cnt[i])+mod-1)%mod*mbs[i]%mod+mod)%mod;
        (ans+=tmp)%=mod;
    }
    printf("%I64d
",ans);
    return 0;
}
View Code

G. Periodic RMQ Problem

题意:有k个数,重复n次,组成的1e9的序列,区间修改+区间询问最小值

解法:ST表+线段树动态开点裸题

技术分享图片
233
View Code

 

以上是关于Educational Codeforces Round 20解(bu)题记录的主要内容,如果未能解决你的问题,请参考以下文章

Educational Codeforces Round 7 A

Educational Codeforces Round 7

Educational Codeforces Round 90

Educational Codeforces Round 33

Codeforces Educational Codeforces Round 54 题解

Educational Codeforces Round 27