zoukankan      html  css  js  c++  java
  • 2019牛客多校训练(二)

    比赛链接:

    https://ac.nowcoder.com/acm/contest/882#question

    A.Eddy Walker

    题意:

    在一个$n$个节点的环中,一个人随机向前或者向后,求出他刚好走过所有节点时,位于$m$点的概率

    分析:

    对于$n$等于18,我们可以用随机数模拟移动的方向,记录以$i$点结束的次数

    发现,除了0点不可能结束,其它点结束的概率相同,那么概率就只能是$frac{1}{n-1}$

    ac代码:

    #include<bits/stdc++.h>
    #define ll long long
    #define ull unsigned long long
    #define pa pair<int,int>
    using namespace std;
    const int maxn=14+5;
    const int maxm=1e7+10;
    const ll mod=1e9+7;
    ll qpow(ll x,ll y)
    {
        ll res=1,k=x;
        while(y)
        {
            if(y%2)res=res*k%mod;
            k=k*k%mod;
            y/=2;
        }
        return res;
    }
    int main()
    {
        //cout<<qpow(2,10)<<endl;
        int T,n,m;
        scanf("%d",&T);
        ll ans=1;
        while(T--)
        {
            scanf("%d %d",&n,&m);
            if(n==1&&m==0)
                ;
            else if(n!=0&&m==0)
                ans=0;
            else
                ans=ans*qpow((n-1),mod-2)%mod;
            printf("%lld
    ",ans);
        }
        return 0;
    }
    

      

    F.Partition problem

    题意:

    总共有$2n$个人,分成两队

    如果a,b不在一队那么竞争值+$V_{ab}$

    求最大竞争值

    分析:

    用dfs暴力搜索在$2n$人里面选择$n$个人的所有情况,注意每次加人和减人都去除或添加点的影响,而不要等在搜索到结果再执行这个操作

    这样,复杂度从$C(2n,n)n^{2}$降到了$C(2n,n)n$,因为给了四秒,刚好可以跑过去

    ac代码:

    #include<bits/stdc++.h>
    #define ll long long
    #define ull unsigned long long
    #define pa pair<int,int>
    using namespace std;
    const int maxn=14+5;
    const int maxm=1e7+10;
    const ll mod=998244353;
    int num[maxn],ma[maxn*2][maxn*2],n;
    ll v[maxn*2],ans;
    bool vis[maxn*2];
    void dfs(int s,int f)
    {
    
        if(s-f>n)return ;
        if(vis[s])
        {
            vis[s]=false;
            for(int j=1;j<=2*n;j++)v[j]-=ma[s][j];
        }
        num[f]=s;
        if(f==n)
        {
            ll res=0;
            for(int i=1;i<=n;i++)
                res+=v[num[i]];
    //        for(int i=1;i<=2*n;i++)
    //            cout<<vis[i]<<" ";
    //        cout<<endl;
            ans=max(ans,res);
           // cout<<res<<endl;
            return ;
        }
        for(int i=s+1;i<=2*n;i++)
        {
            dfs(i,f+1);
            if(vis[i]==false)
            {
                vis[i]=1;
                for(int j=1;j<=2*n;j++)v[j]+=ma[i][j];
            }
        }
    
    }
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<=2*n;i++)
            for(int j=1;j<=2*n;j++)
                scanf("%d",&ma[i][j]);
    
        for(int i=1;i<=2*n;i++)vis[i]=true;
        for(int i=1;i<=2*n;i++)for(int j=1;j<=2*n;j++)v[i]+=ma[i][j];
    
        for(int i=1;i<=2*n;i++)
        {
            dfs(i,1);
            if(vis[i]==false)
            {
                vis[i]=true;
                for(int j=1;j<=2*n;j++)v[j]+=ma[i][j];
            }
        }
        printf("%lld
    ",ans);
        return 0;
    }
    

      

    H.Second Large Rectangle

    题意:

     在01矩阵中求出第二大的全1矩阵,只需要输出矩阵大小

    分析:

     用单调栈求出以第$i$行为底的所有极大全1矩阵,把原矩阵和少一列的矩阵放入结果集,每次保留两个结果

    两次单调栈好写,其实一次单调栈也可以求出解

    ac代码:

    #include<bits/stdc++.h>
    #define ll long long
    #define ull unsigned long long
    #define pa pair<int,int>
    using namespace std;
    const int maxn=1e3+5;
    const int maxm=1e7+10;
    const ll mod=998244353;
    char word[maxn][maxn];
    int num[maxn][maxn];
    int zz[maxn];
    int n,m,top,l[maxn],r[maxn];
    pa sk[maxn];
    int ans[3];
    bool vis[maxn][maxn];
    void add(int x)
    {
        ans[0]=x;
        sort(ans,ans+3);
    }
    void work(int x,int y)
    {
     
        int v=l[y],w=r[y];
        if(vis[v][w])return ;
        vis[v][w]=true;
        add((w-v)*num[x][y]);
        add((w-v+1)*num[x][y]);
    }
    int main()
    {
     
        scanf("%d %d",&n,&m);
        for(int i=1;i<=n;i++)scanf("%s",word[i]+1);
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
                if(word[i][j]=='1')num[i][j]=num[i-1][j]+1;
     
        for(int i=1;i<=n;i++)
        {
     
            for(int j=1;j<=m;j++)
            {
                while(top&&sk[top].first>num[i][j])
                {
                    r[sk[top].second]=j-1;
                    top--;
                }
                sk[++top]=make_pair(num[i][j],j);
            }
            while(top)r[sk[top].second]=m,top--;
            for(int j=m;j>=1;j--)
            {
                while(top&&sk[top].first>num[i][j])
                {
                    l[sk[top].second]=j+1;
                    top--;
                }
                sk[++top]=make_pair(num[i][j],j);
            }
            while(top)l[sk[top].second]=1,top--;
     
            for(int j=1;j<=m;j++)work(i,j);
            for(int j=1;j<=m;j++)vis[l[j]][r[j]]=false,l[j]=r[j]=0;
        }
        printf("%d
    ",ans[1]);
        return 0;
    }
    

      

  • 相关阅读:
    CSS实现返回网页顶部
    jQuery实现小火箭动态返回顶部代码
    Linux目录结构介绍
    Linux常用命令及技巧
    Linux文件系统
    Linux特性
    numpy中基础函数
    restful规范
    堆栈
    三次握手与四次挥手
  • 原文地址:https://www.cnblogs.com/carcar/p/11224488.html
Copyright © 2011-2022 走看看