[NowCoder]牛客OI周赛3

A.地斗主

题意:\(4\times N\) 的地板,在上面铺 \(1\times 2\)\(2\times 1\) 的地砖,求铺满方案数, \(N\le 10^9\)

原题。。先把一列的状态压缩成二进制,这一格为1就表示这一格被左边一列横着占用了

为0表示没被左边占用(放了竖着的或者没放都是一样的)

可以推出一系列转移,最后发现有用状态只有6个,有两个方案数总是一样,可以合并

因此用矩阵乘法加速递推即可

#include<bits/stdc++.h>
#define REP(i,a,b) for(int i(a);i<=(b);++i)
using namespace std;
typedef long long ll;
inline int read(){char c,p=0;int w;
    while(isspace(c=getchar()));if(c=='-')p=1,c=getchar();
    for(w=c&15;isdigit(c=getchar());w=w*10+(c&15));return p?-w:w;
}
int n,m;
struct mat{
    int v[5][5];
    mat(){memset(v,0,sizeof v);}
    inline int*operator[](const int&i){return v[i];}
    inline mat operator*(mat&r){
        mat ans;REP(k,0,4)REP(i,0,4)REP(j,0,4)
        ans[i][j]=(ans[i][j]+1ll*v[i][k]*r[k][j])%m;
        return ans;
    }
}A,B,C;
inline mat fpow(mat x,int k){
    mat r;REP(i,0,4)r[i][i]=1;
    for(;k;k>>=1,x=x*x)if(k&1)r=r*x;return r;
}
int main(){
    A[0][0]=A[0][1]=A[0][4]=1;A[0][2]=2;
    A[1][0]=A[2][0]=1,A[2][2]=1,A[3][4]=1,
    A[4][0]=A[4][3]=1;
    B[0][0]=1;
    int T=read();
    while(T--){
        n=read(),m=read();
        C=fpow(A,n)*B;
        io.print(C[0][0]);
    }
    return 0;
}

B.1048

题意:\(N\) 个白球和 \(N\) 个黑球,每个都以 \(1\dots N\) 标号,现在给出每个球的颜色和标号,要求用最少的步数邻项交换,使得白球是有序的,黑球也是有序的,\(N\le 2000\)

由邻项交换可以想到冒泡排序,冒泡排序的最小交换次数是逆序对,考虑DP

\(f[i][j]\) 表示 已经排了前 \(i\) 个白球,前 \(j\) 个黑球的最小代价,若用 \(i\) 转移,则代价是 在 \(i\) 前面,比 \(i\) 大的白球数目 和 在 \(i\) 前面, 比 \(j\) 大的黑球数目,简单起见用 \(c1[i]\) 表示;同理若用 \(j\) 转移,代价是 \(c2[j]\)
\[ f[i][j]=min(f[i-1][j]+c1[i],f[i][j-1]+c2[j]) \]

#include<bits/stdc++.h>
#define REP(i,a,b) for(int i(a);i<=(b);++i)
#define dbg(...) fprintf(stderr,__VA_ARGS__)
using namespace std;
template<typename T,typename U>inline char smin(T&x,const U&y){return x>y?x=y,1:0;}
template<typename T,typename U>inline char smax(T&x,const U&y){return x<y?x=y,1:0;}
const int N=2005;
int n,f[N][N],p[2][N],cnt[2][N<<1][N];
int main(){
    scanf("%d",&n);
    REP(i,1,n<<1){
        char c;int x;scanf("%s%d",&c,&x);
        p[c=='B'][x]=i;
        REP(j,i,n<<1)++cnt[c=='B'][j][x];
    }
    REP(k,0,1)REP(i,1,n<<1)for(int j=n;~j;--j)cnt[k][i][j]+=cnt[k][i][j+1];
    REP(i,0,n)REP(j,0,n){
        if(i||j)f[i][j]=1e9;
        if(i)smin(f[i][j],f[i-1][j]+cnt[1][p[0][i]-1][j+1]+cnt[0][p[0][i]-1][i+1]);
        if(j)smin(f[i][j],f[i][j-1]+cnt[0][p[1][j]-1][i+1]+cnt[1][p[1][j]-1][j+1]);
    }
    cout<<f[n][n];
    return 0;
}

C.爆瓶子

题意:你有 \(N\) 种瓶子每种 \(N\) 个,需要把它排成 \(N\times N\) 的方阵,要求每行每列不能有相同瓶子,输出字典序最小的方案 \(N \le 220\)

垃圾题,跟着数据卡数据范围,暴力二分图匹配

一行一行进行二分图匹配,匹配了就把对应的边删掉,得出一组匹配后再看能不能和前面交换得到字典序更小的匹配

#include<bits/stdc++.h>
#define REP(i,a,b) for(int i(a);i<=(b);++i)
using namespace std;
inline int read(){char c,p=0;int w;
    while(isspace(c=getchar()));if(c=='-')p=1,c=getchar();
    for(w=c&15;isdigit(c=getchar());w=w*10+(c&15));return p?-w:w;
}
const int N=225;
int n,m,head[N],pre[N][N],nxt[N][N],vis[N],T,bel[N],to[N];
inline void del(int i,int j){
    if(j==head[i])head[i]=nxt[i][j];
    else pre[i][nxt[i][j]]=pre[i][j],nxt[i][pre[i][j]]=nxt[i][j];
}
inline bool dfs(int x,int lim){
    for(int i=head[x];i;i=nxt[x][i])if(vis[i]!=T){
        vis[i]=T;
        if(!bel[i]||bel[i]>lim&&dfs(bel[i],lim))
        return to[x]=i,bel[i]=x,1;
    }
    return 0;
}
inline void solve(){
    REP(i,1,n)++T,dfs(i,0);
    REP(i,1,n){
        ++T;
        for(int j=head[i];j;j=nxt[i][j]){
            if(bel[j]==i)break;
            if(bel[j]<i)continue;
            int x=bel[j],y=to[i];
            to[i]=j,bel[j]=i,to[x]=bel[y]=0;
            if(dfs(x,i))break;
            to[x]=j,bel[j]=x,to[i]=y,bel[y]=i;
        }
    }
}
int main(){
    int t=read();
    while(t--){
        n=read();m=read();
        REP(i,1,n){
            REP(j,1,n)pre[i][j]=j-1,nxt[i][j]=j+1;nxt[i][n]=0;head[i]=1;
        }
        REP(i,1,m)REP(j,1,n)del(j,read());
        REP(i,m+1,n){
            memset(to,0,sizeof to);
            memset(bel,0,sizeof bel);
            memset(vis,0,sizeof vis);
            T=0,solve();
            REP(j,1,n)del(j,to[j]),printf("%d ",to[j]);puts("");
        }
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/HolyK/p/9835130.html