Codeforces Round #592 (Div. 2)

(一道sb题卡了我40min,成功GG)

A:

送分题。sry说他没看懂所以先开D然后成功吊打我,看来Div2不能顺着开题。。

#include<bits/stdc++.h>
#define maxn 100005
#define maxm 500005
#define inf 0x7fffffff
#define ll long long

using namespace std;

inline int read(){
    int x=0,f=1; char c=getchar();
    for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
    for(;isdigit(c);c=getchar()) x=x*10+c-'0';
    return x*f;
}

int main(){
    int t=read();
    while(t--){
        int a=read(),b=read(),c=read(),d=read(),k=read();
        int t1=a/c+(a%c?1:0),t2=b/d+(b%d?1:0);
        if(t1+t2<=k) cout<<t1<<" "<<t2<<endl; 
        else cout<<-1<<endl;
    }
    return 0;
}
A

B:

送分题。

#include<bits/stdc++.h>
#define maxn 1005
#define maxm 500005
#define inf 0x7fffffff
#define ll long long

using namespace std;
char str[maxn];

inline int read(){
    int x=0,f=1; char c=getchar();
    for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
    for(;isdigit(c);c=getchar()) x=x*10+c-'0';
    return x*f;
}

int main(){
    int T=read();
    while(T--){
        int n=read();
        cin>>str+1;
        int l=0,r=0,ans=n,flag=0;
        for(int i=1;i<=n;i++){
            if(str[i]=='1' && !flag) l=i,flag=1;
            if(str[i]=='1') ans=max(ans,max(i*2,(n-i+1)*2));
        }
        for(int i=n;i>=1;i--)
            if(str[i]==1)
                {r=i;break;} 
        if(!l) cout<<ans<<endl;
        else if(l==r) cout<<ans<<endl;
        else cout<<max(ans,(r-l+1)*2+max(l-1,n-r))<<endl;
    }
    return 0;
}
B

C:

回收开头。

题意简洁明了,求方程$ax+by=c$的一组正整数解,满足$x+y\leq n$

数据范围$n\leq 10^{12},c\leq 10^{17},b<a\leq 10^{5}$

花了10min写了一个exgcd,然后wa on 5。当时我就自闭了。

注意到exgcd求出答案后要乘$\frac{c}{gcd(a,b)}$,而这个会爆long long,cf又好像不支持__int128。

换一种思路,能不能求一个x使得$ax\equiv c(mod b)$呢?

容易发现(根据剩余系相关知识),至多枚举b个x就会出现0。

如果我们将x从大往小枚举,那么当第一次出现一个x满足题意时,这个答案一定是a最多且b最少的。

此时由于$a>b$,那么$(x+y)$的值一定是最小的。(用大物品和小物品装背包,大物品个数较多时总个数一定较少)

(这题堪称经典sb题,看到题解就知道自己应该退役了。)

#include<bits/stdc++.h>
#define maxn 100005
#define maxm 500005
#define inf 0x7fffffff
#define ll long long

using namespace std;

inline ll read(){
    ll x=0,f=1; char c=getchar();
    for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
    for(;isdigit(c);c=getchar()) x=x*10+c-'0';
    return x*f;
}

int main(){
    ll n=read(),p=read(),a=read(),b=read(),x=p/a,T=maxn;
    while(T--){
        if((p-x*a)%b==0){
            if(x<0 || x+(p-x*a)/b>n){cout<<-1<<endl;return 0;}
            else{cout<<x<<" "<<(p-x*a)/b<<" "<<n-(x+(p-x*a)/b)<<endl;return 0;}
        }
        x--;
    }
    cout<<-1<<endl;
    return 0;
}
C

D:

送分题,注意到只有一条链满足题意就完事了。

(那么div2开题应该从D开始开?)

#include<bits/stdc++.h>
#define maxn 100005
#define maxm 500005
#define inf 0x7fffffff
#define ll long long

using namespace std;
int N,hd[maxn],to[maxn<<1],nxt[maxn<<1],cnt,siz[maxn],deg[maxn];
ll cst[3][maxn],dp[maxn][3][3];
int from[maxn][3][3][2],cl[maxn];

inline ll read(){
    ll x=0,f=1; char c=getchar();
    for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
    for(;isdigit(c);c=getchar()) x=x*10+c-'0';
    return x*f;
}

inline void addedge(ll u,ll v){
    to[++cnt]=v,nxt[cnt]=hd[u],hd[u]=cnt;
}

inline void dfs(int u,int fa){
    int son=0;
    //cout<<u<<":"<<fa<<endl;
    for(int i=hd[u];i;i=nxt[i])
        if(to[i]!=fa) son=to[i],dfs(son,u);
    //cout<<son<<endl;
    if(!son){
        for(int i=0;i<3;i++) 
            dp[u][i][i]=cst[i][u];
        return;
    }
    for(int i=0;i<3;i++)
        for(int j=0;j<3;j++)
            for(int k=0;k<3;k++)
                if(dp[u][i][j]>dp[son][j][k]+cst[i][u] && i!=j && i!=k)
                    dp[u][i][j]=dp[son][j][k]+cst[i][u],from[u][i][j][0]=j,from[u][i][j][1]=k;
    return;
}

inline void find(int u,int fa,int x,int y){
    cl[u]=x;
    int son=0;
    for(int i=hd[u];i;i=nxt[i])
        if(to[i]!=fa) son=to[i];
    if(son) find(son,u,from[u][x][y][0],from[u][x][y][1]);
    return;
}

int main(){
    memset(dp,127,sizeof(dp));
    N=read();
    for(ll k=0;k<3;k++)
        for(ll i=1;i<=N;i++) cst[k][i]=read();
    for(ll i=1;i<=N-1;i++){
        ll u=read(),v=read();
        addedge(u,v),addedge(v,u);
        deg[u]++,deg[v]++;
    }
    bool flag=0;
    ll num=0,rt=0;
    for(ll i=1;i<=N;i++){
        if(deg[i]>=3){flag=1;break;}
        if(deg[i]==1) rt=i;
    }
    if(flag) cout<<-1<<endl;
    else{
        dfs(rt,0);
        ll ans=(1ll<<62),r1=0,r2=0;
        for(int i=0;i<3;i++)
            for(int j=0;j<3;j++)
                if(dp[rt][i][j]<ans)
                    ans=dp[rt][i][j],r1=i,r2=j;
        find(rt,0,r1,r2);
        cout<<ans<<endl;
        for(int i=1;i<=N;i++)
            cout<<cl[i]+1<<" ";
        cout<<endl;
    }
    return 0;
}
D

E:

送分题,枚举最大值取哪个点后二分最小值求答案。

由于开题顺序错误所以看到这题的时候还有大概5分钟。

秒出做法然而并没有什么软用。

明天补后面的题,先开一把吃鸡。

猜你喜欢

转载自www.cnblogs.com/YSFAC/p/11668798.html