1. 程式人生 > 實用技巧 >Codeforces Round #663 (Div. 2)訓練小結

Codeforces Round #663 (Div. 2)訓練小結

連結

Virtual participation

A. Suborrays

觀察發現任何排列均滿足題意。

#include<bits/stdc++.h>
using namespace std;
int N;
int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
    int T;cin>>T;
    while(T--){
        cin>>N;
        for(int i=1;i<=N;++i)
            printf("%d ",i);
        puts("");
    }
    return 0;
}

B. Fix You

由於要求從任意位置都能走到右下角,只要讓最後一行均為“R”,最後一列均為“D”即可。可以證明這是最優解。

#include<bits/stdc++.h>
using namespace std;
int N,M,ans;
char A[110][110];
int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
    int T;cin>>T;
    while(T--){
        ans=0;
        cin>>N>>M;
        for(int i=1;i<=N;++i)
            cin>>A[i]+1;
        for(int i=1;i<N;++i)
            if(A[i][M]!='D')
                ++ans;
        for(int j=1;j<M;++j)
            if(A[N][j]!='R')
                ++ans;
        printf("%d\n",ans);
    }
    return 0;
}

C. Cyclic Permutations

組合數學。

觀察發現,只有最大數的左側升序,右側降序的排列符合題意。

#include<bits/stdc++.h>
using namespace std;
const int mod=1e9+7;
int N,fac[1000010],ifac[1000010];
long long ans;
int C(int n,int m){
    if(n<m)return 0;
    return 1ll*fac[n]*ifac[m]%mod*ifac[n-m]%mod;
}
int qpow(int base,int b){
    int res=1;
    while(b){
        if(b&1)res=1ll*res*base%mod;
        base=1ll*base*base%mod;
        b>>=1;
    }
    return res;
}
int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
    cin>>N;
    fac[0]=1;
    for(int i=1;i<=N;++i)
        fac[i]=1ll*fac[i-1]*i%mod;
    ifac[N]=qpow(fac[N],mod-2);
    for(int i=N;i>=1;--i)
        ifac[i-1]=1ll*ifac[i]*i%mod;
    ans=fac[N];
    for(int i=1;i<=N;++i)
        ans=(ans-C(N-1,i-1)+mod)%mod;
    printf("%lld\n",ans);
    return 0;
}

D. 505

狀壓DP。

\(N\ge 4\)\(M\ge 4\) 時,不存在解。所以行/列不超過3,且只需要考慮 \(2\times 2\) 的子矩陣即可。顯然可以狀壓DP。記 \(f(i,S)\) 表示“做到第 \(i\) 行(列),當前行(列)的01序列為 \(S\) ”的最少步驟數。

#include<bits/stdc++.h>
using namespace std;
int N,M,A[1000010],B[5],ans;
int F[1000010][10];
char str[1000010];
int getPos(int x,int y){
    return x*M+y;
}
int isRight(int k1,int k2,int x){
    memset(B,0,sizeof(B));
    for(int i=0;i<x;++i,k1>>=1,k2>>=1)
        B[i]=(k1&1)+(k2&1);
    for(int i=1;i<x;++i)
        if((B[i-1]+B[i])%2==0)
            return 0;
    return 1;
}
int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
    cin>>N>>M;ans=1e6;
    for(int i=0;i<N;++i){
        cin>>str;
        for(int j=0;j<M;++j)
            A[getPos(i,j)]=str[j]-'0';
    }
    if(N>=4&&M>=4)puts("-1");
    else{
        int tmp;
        if(N<2||M<2)puts("0");
        else if(N<4){
            for(int j=0;j<M;++j)
                for(int k=0;k<(1<<N);++k)
                    F[j][k]=1e6;
            for(int k=0;k<(1<<N);++k){
                F[0][k]=0;
                for(int i=0;i<N;++i)
                    F[0][k]+=(A[getPos(i,0)]!=((k>>i)&1));
            }
            for(int j=1;j<M;++j)
                for(int k1=0;k1<(1<<N);++k1)
                    for(int k2=0;k2<(1<<N);++k2)
                        if(isRight(k1,k2,N)){
                            tmp=0;
                            for(int i=0;i<N;++i)
                                tmp+=(A[getPos(i,j)]!=((k2>>i)&1));
                            F[j][k2]=min(F[j][k2],F[j-1][k1]+tmp);
                        }
            for(int k=0;k<(1<<N);++k)
                ans=min(ans,F[M-1][k]);
            printf("%d\n",ans);
        }
        else if(M<4){
            for(int i=0;i<N;++i)
                for(int k=0;k<(1<<M);++k)
                    F[i][k]=1e6;
            for(int k=0;k<(1<<M);++k){
                F[0][k]=0;
                for(int j=0;j<M;++j)
                    F[0][k]+=(A[getPos(0,j)]!=((k>>j)&1));
            }
            for(int i=1;i<N;++i)
                for(int k1=0;k1<(1<<M);++k1)
                    for(int k2=0;k2<(1<<M);++k2)
                        if(isRight(k1,k2,M)){
                            tmp=0;
                            for(int j=0;j<M;++j)
                                tmp+=(A[getPos(i,j)]!=((k2>>j)&1));
                            F[i][k2]=min(F[i][k2],F[i-1][k1]+tmp);
                        }
            for(int k=0;k<(1<<M);++k)
                ans=min(ans,F[N-1][k]);
            printf("%d\n",ans);
        }
    }
    return 0;
}

總結

整體做的還不錯。