牛客多校第二场

  

A:题意: 有一个n个点的圈标号为0-n-1    每次只能向相邻方向走一步  两个方向随机  每走到一个新的格子都会设立一个标记 (一开始在0设立标记) 问最后停在第m个格子的概率为多少   输出答案积

概率为1/(n-1)    注意m为0的特殊情况即可

#include<bits/stdc++.h>
using namespace std;
//input by bxd
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define repp(i,a,b) for(int i=(a);i>=(b);--i)
#define RI(n) scanf("%d",&(n))
#define RII(n,m) scanf("%d%d",&n,&m)
#define RIII(n,m,k) scanf("%d%d%d",&n,&m,&k)
#define RS(s) scanf("%s",s);
#define ll long long
#define pb push_back
#define inf 0x3f3f3f3f
#define CLR(A,v)  memset(A,v,sizeof A)
//////////////////////////////////
const int N=101;
const ll mod=1e9+7;
ll fast(ll x,ll n){ll ans=1;while(n){if(n&1)ans*=x,ans%=mod;x*=x;x%=mod;n>>=1 ; }return ans;  }
ll n,m;
int main()
{
    ll ans=1;int cas;RI(cas);
    while(cas--)
    {
        scanf("%lld%lld",&n,&m);
        ll res;
        if(m==0)res=(n>1)?0:1;
        else res=fast(n-1,mod-2);
        ans*=res,ans%=mod;
        cout<<ans<<endl;
    }



    return 0;
}
View Code

D:给出一个无向点权图  问点权第k大的团的点权为多少  

bfs遍历即可  设置一个点权优先队列

使用bitset来表示路径和 包含点 非常方便

#include<bits/stdc++.h>
using namespace std;
//input by bxd
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define repp(i,a,b) for(int i=(a);i>=(b);--i)
#define RI(n) scanf("%d",&(n))
#define RII(n,m) scanf("%d%d",&n,&m)
#define RIII(n,m,k) scanf("%d%d%d",&n,&m,&k)
#define RS(s) scanf("%s",s);
#define ll long long
#define pb push_back
#define inf 0x3f3f3f3f
#define CLR(A,v)  memset(A,v,sizeof A)
//////////////////////////////////
const int N=101;
struct node
{
    ll sum;
    int id;
    bitset<N>s;
    bool operator < (const node & b)const
    {
        return sum>b.sum;
    }
};

int n,k,v[N];
char ss[N];
bitset<N>e[N];
ll sol()
{
    RII(n,k);
    rep(i,1,n)RI(v[i]);

    rep(i,1,n)
    {
        RS(ss+1);
        rep(j,1,n)
        {
            if(ss[j]=='1')e[i].set(j);
        }
    }
    bitset<N>s;
    s.reset();
    priority_queue<node>q;
    q.push(node{0,0,s});

    while(!q.empty())
    {
        node u=q.top();q.pop();
        if(--k==0)return u.sum;
        rep(i,u.id+1,n)
        {
            if(!u.s[i]&&(u.s&e[i])==u.s)
            {
                u.s.set(i);
                q.push(node{u.sum+1ll*v[i],i,u.s });
                u.s.reset(i);
            }
        }
    }

    return -1;
}
int main()
{
    printf("%lld",sol());
}
View Code

E:

给出一个nm 01矩阵 (迷宫)  1代表墙不能走  

操作一  将x行y列 这个点反转  

操作二  问第一行的x点到第n行的y点的路径个数

用矩阵乘法来计算路径个数  用线段树来维护

#include<bits/stdc++.h>
using namespace std;
//input by bxd
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define repp(i,a,b) for(int i=(a);i>=(b);--i)
#define RI(n) scanf("%d",&(n))
#define RII(n,m) scanf("%d%d",&n,&m)
#define RIII(n,m,k) scanf("%d%d%d",&n,&m,&k)
#define RS(s) scanf("%s",s);
#define ll long long
#define pb push_back
#define inf 0x3f3f3f3f
#define lson l,m,pos<<1
#define rson m+1,r,pos<<1|1
#define CLR(A,v)  memset(A,v,sizeof A)
//////////////////////////////////
const int N=1e4;
const int mod=1e9+7;
int n,m,q,b[50000+10][11];
struct Matrix
{
    ll a[11][11];
    friend Matrix operator*(const Matrix &a,const Matrix &b)
    {
        Matrix c;CLR(c.a,0);
        rep(i,1,m)rep(k,1,m)rep(j,1,m)
        c.a[i][j]=(c.a[i][j]+1ll*a.a[i][k]*b.a[k][j])%mod;
        return c;
    }
}
t[200000+10];

void change(int *b,Matrix &ans)
{
    CLR(ans.a,0);
    rep(i,1,m)
    {
        int j=i;
        for(;j>=1&&!b[j];ans.a[i][j]=1,--j);
        j=i;
        for(;j<=m&&!b[j];ans.a[i][j]=1,j++);
    }
}
void build(int l,int r,int pos)
{
    if(l==r){change(b[l],t[pos]);return ;}
    int m=(l+r)>>1;build(lson);build(rson);
    t[pos]=t[pos<<1]*t[pos<<1|1];
}

void up(int x,int l,int r,int pos)
{
    if(l==r){change(b[l],t[pos]);return ; }
    int m=(l+r)>>1;
    if(x<=m)up(x,lson);
    else if(x>m)up(x,rson);
    t[pos]=t[pos<<1]*t[pos<<1|1];
}
char s[100];
int main()
{
    scanf("%d%d%d",&n,&m,&q);
    rep(i,1,n){scanf("%s",s+1);rep(j,1,m)b[i][j]=s[j]-'0';}
    build(1,n,1);
    while(q--)
    {
        ll op,x,y;
        scanf("%lld%lld%lld",&op,&x,&y);
        if(op==1)b[x][y]^=1,up(x,1,n,1);
        else if(op==2)printf("%lld
",t[1].a[x][y]);
    }
}
View Code

F:

有2*n个人   和两个队伍 将这2*n个人分配到两个队伍使得每个队伍恰好n个人

如果两个人分配到两个队伍会产生一个冲突mp[i][j](条件给出)  问能产生的最大冲突

dfs

如果dfs找到n个后再计算贡献呢的话复杂度为 C(2n,n) *n2

可以边dfs边计算贡献  那么复杂度可以减一个n

#include<bits/stdc++.h>
using namespace std;
//input by bxd
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define repp(i,a,b) for(int i=(a);i>=(b);--i)
#define RI(n) scanf("%d",&(n))
#define RII(n,m) scanf("%d%d",&n,&m)
#define RIII(n,m,k) scanf("%d%d%d",&n,&m,&k)
#define RS(s) scanf("%s",s);
#define ll long long
#define pb push_back
#define inf 0x3f3f3f3f
#define CLR(A,v)  memset(A,v,sizeof A)
//////////////////////////////////
const int N=1001;

ll sum[N],mp[N][N],ans,ans1,vis[N];
int n;

void dfs(int cur,int num)
{
    if(num==n+1)
    {
        ans=max(ans,ans1);return ;
    }
    rep(i,cur+1,2*n)
    {
        ll k=ans1;
        vis[num]=i;
        ans1+=sum[i];
        rep(j,1,num-1)
        ans1-=mp[i][vis[j]]*2;
        dfs(i,num+1);
        ans1=k;
    }
}

int main()
{
    RI(n);
    rep(i,1,2*n)rep(j,1,2*n)scanf("%lld",&mp[i][j]),sum[i]+=mp[i][j];
    dfs(0,1);
    cout<<ans;
    return 0;
}
View Code

H

求第二大矩形

比赛的时候扣四个点分别dp

也可以用单调栈来维护

#include<bits/stdc++.h>
using namespace std;
//input by bxd
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define repp(i,a,b) for(int i=(a);i>=(b);--i)
#define RI(n) scanf("%d",&(n))
#define see(x) (cerr<<(#x)<<'='<<(x)<<endl)
#define RII(n,m) scanf("%d%d",&n,&m)
#define RIII(n,m,k) scanf("%d%d%d",&n,&m,&k)
#define RS(s) scanf("%s",s);
#define ll long long
#define REP(i,N)  for(int i=0;i<(N);i++)
#define CLR(A,v)  memset(A,v,sizeof A)
#define inf 0x3f3f3f3f
//////////////////////////////////
const int N=1000+5;
int dp[N][N];
char mp[N][N];
int ri[N][N],le[N][N],up[N][N];
int main()
{
    int s;
    int n,m;
    RII(n,m);

    rep(i,1,n)RS(mp[i]+1);

    rep(i,1,n)
    rep(j,1,m)
    {
        if(mp[i][j]=='1')mp[i][j]=1;
        else mp[i][j]=0;
        ri[i][j]=le[i][j]=j;
        up[i][j]=1;
    }
    rep(i,1,n)
    rep(j,2,m)
    if(mp[i][j]==mp[i][j-1]&&mp[i][j]==1)
    le[i][j]=le[i][j-1];
    rep(i,1,n)
    repp(j,m-1,1)
    if(mp[i][j]==mp[i][j+1]&&mp[i][j]==1)
    ri[i][j]=ri[i][j+1];

    int ans=0,maxx=0;
    int flagx=-1,flagy=-1;




    int chang,gao;
    rep(i,1,n)
    rep(j,1,m)
    if(mp[i][j])
    {
       if(i>1)
           if(mp[i-1][j])//如果状态需要转移的话
           {
            le[i][j]=max(le[i][j],le[i-1][j]);
            ri[i][j]=min(ri[i][j],ri[i-1][j]);
            up[i][j]=up[i-1][j]+1;
           }
        int d=ri[i][j]-le[i][j]+1;
        if(d*up[i][j]>maxx)
        {
            maxx=d*up[i][j];
            s=d*up[i][j];

            flagx=i;flagy=j;
            chang=d;gao=up[i][j];
            ans=max(s-d,s-(s/d));
        }
    }
    int x1,yy,x2,y2,x3,y3,x4,y4;
    //see(flagx);see(flagy);see(chang);see(gao);

    int shang=flagx-gao+1;
    int L=0,R=inf;
    //see(shang);
    rep(i,shang,flagx)
    {
        int l=flagy,r=flagy;
        while(mp[i][l-1]==1&&l-1>=1)l--;
        while(mp[i][r+1]==1&&r+1<=m)r++;
        L=max(L,l);
        R=min(R,r);
    }

    //see(L);see(R);
    x1=x2=shang;
    x3=x4=flagx;
    yy=L;y2=R;
    y3=L;y4=R;
    //see(x1);see(yy);see(x2);see(y2);see(x3);see(y3);see(x4);see(y4);

        maxx=0;
        mp[x1][yy]=0;
        rep(i,1,n)
        rep(j,1,m)
        {
            ri[i][j]=le[i][j]=j;
            up[i][j]=1;
        }
        rep(i,1,n)
        rep(j,2,m)
        if(mp[i][j]==mp[i][j-1]&&mp[i][j]==1)
        le[i][j]=le[i][j-1];
        rep(i,1,n)
        repp(j,m-1,1)
        if(mp[i][j]==mp[i][j+1]&&mp[i][j]==1)
        ri[i][j]=ri[i][j+1];
        rep(i,1,n)
        rep(j,1,m)
        if(mp[i][j])
        {
                if(i>1)
               if(mp[i-1][j])//如果状态需要转移的话
               {
                    le[i][j]=max(le[i][j],le[i-1][j]);
                    ri[i][j]=min(ri[i][j],ri[i-1][j]);
                    up[i][j]=up[i-1][j]+1;
               }
            int d=ri[i][j]-le[i][j]+1;
            s=d*up[i][j];
            maxx=max(maxx,s);
        }
        mp[x1][yy]=1;

        mp[x2][y2]=0;
        rep(i,1,n)
        rep(j,1,m)
        {
            ri[i][j]=le[i][j]=j;
            up[i][j]=1;
        }
        rep(i,1,n)
        rep(j,2,m)
        if(mp[i][j]==mp[i][j-1]&&mp[i][j]==1)
        le[i][j]=le[i][j-1];
        rep(i,1,n)
        repp(j,m-1,1)
        if(mp[i][j]==mp[i][j+1]&&mp[i][j]==1)
        ri[i][j]=ri[i][j+1];
        rep(i,1,n)
        rep(j,1,m)
        if(mp[i][j])
        {
                if(i>1)
               if(mp[i-1][j])//如果状态需要转移的话
               {
                    le[i][j]=max(le[i][j],le[i-1][j]);
                    ri[i][j]=min(ri[i][j],ri[i-1][j]);
                    up[i][j]=up[i-1][j]+1;
               }
            int d=ri[i][j]-le[i][j]+1;
            s=d*up[i][j];
            maxx=max(maxx,s);
        }
        mp[x2][y2]=1;

        mp[x3][y3]=0;
        rep(i,1,n)
        rep(j,1,m)
        {
            ri[i][j]=le[i][j]=j;
            up[i][j]=1;
        }
        rep(i,1,n)
        rep(j,2,m)
        if(mp[i][j]==mp[i][j-1]&&mp[i][j]==1)
        le[i][j]=le[i][j-1];
        rep(i,1,n)
        repp(j,m-1,1)
        if(mp[i][j]==mp[i][j+1]&&mp[i][j]==1)
        ri[i][j]=ri[i][j+1];
        rep(i,1,n)
        rep(j,1,m)
        if(mp[i][j])
        {
                if(i>1)
               if(mp[i-1][j])//如果状态需要转移的话
               {
                    le[i][j]=max(le[i][j],le[i-1][j]);
                    ri[i][j]=min(ri[i][j],ri[i-1][j]);
                    up[i][j]=up[i-1][j]+1;
               }
            int d=ri[i][j]-le[i][j]+1;
            s=d*up[i][j];
            maxx=max(maxx,s);
        }
        mp[x3][y3]=1;

        mp[x4][y4]=0;
        rep(i,1,n)
        rep(j,1,m)
        {
            ri[i][j]=le[i][j]=j;
            up[i][j]=1;
        }
        rep(i,1,n)
        rep(j,2,m)
        if(mp[i][j]==mp[i][j-1]&&mp[i][j]==1)
        le[i][j]=le[i][j-1];
        rep(i,1,n)
        repp(j,m-1,1)
        if(mp[i][j]==mp[i][j+1]&&mp[i][j]==1)
        ri[i][j]=ri[i][j+1];
        rep(i,1,n)
        rep(j,1,m)
        if(mp[i][j])
        {
                if(i>1)
               if(mp[i-1][j])//如果状态需要转移的话
               {
                    le[i][j]=max(le[i][j],le[i-1][j]);
                    ri[i][j]=min(ri[i][j],ri[i-1][j]);
                    up[i][j]=up[i-1][j]+1;
               }
            int d=ri[i][j]-le[i][j]+1;
            s=d*up[i][j];
            maxx=max(maxx,s);
        }
        mp[x4][y4]=1;

        printf("%d
",maxx);


    return 0;
}
View Code
原文地址:https://www.cnblogs.com/bxd123/p/11220535.html