• 2021牛客暑期多校训练营9


    比赛链接:https://ac.nowcoder.com/acm/contest/11260

    E,H,J,10。不错。

    I

    分析:

    题目意思是,(A)和(B)抢夺(n)块地盘,一开始(A)的能力值是(a),(B)的能力值是(b);每抢上一块地盘,抢到的人的能力值会增加(w)。(A)抢上的概率是( frac{A的能力值}{当前总能力值} ),(B)同。问最终(A)抢到地盘数的期望。

    于是可以设(E(x))表示经过(x)轮后(A)的期望能力值。有转移方程:

    ( E(x+1) = E(x) + frac{E(x)}{1+wx}*w )

    移项可以得到:

    ( frac{E(x+1)}{1+w(x+1)} = frac{E(x)}{1+wx} = E(0) = a )

    然后答案可以通过最终的能力值得到,因为能力值和抢几块地盘直接相关:

    ( ans = frac{E(n)-E(0)}{w} = a*n )

    代码如下:

    #include<iostream>
    #define ll long long
    using namespace std;
    int const md=998244353;
    int n,w,x,y;
    ll pw(int a,int b)
    {
        ll ret=1,na=a;
        while(b)
        {
            if(b&1)ret=(ret*na)%md;
            na=(na*na)%md;
            b>>=1;
        }
        return ret;
    }
    int main()
    {
        scanf("%d%d%d%d",&n,&w,&x,&y);
        ll a=(x*pw(y,md-2))%md;
        printf("%lld
    ",a*n%md);
        return 0;
    }
    View Code

    J

    分析:

    首先,右转不会影响任何路线,也不会被任何路线影响,所以单独考虑,最后算答案时比较一下即可。

    剩下的就是左转和直行。观察一番后可以发现,最多有两个灯同时亮起,而且只有四种情况:直行+对面直行,左转+对面左转,直行+左边左转,直行+自己左转。

    换句话说,每个直行有三种灯可以带:前直,左左,自左;每个左转有三种灯可以带:前左,右直,自直。

    所以现在问题可以转化成:默认每个灯单独亮,然后考虑如何安排使得可以相互带的灯实现最大匹配。

    可以拆点,然后二分图匹配——由于还有车流量各种,所以网络流跑一个最大流即可。拆点后会有重复的情况,但是都是对称的,所以直接最大流除以二。

    复习了一下网络流的dinic算法,看了两篇

    代码如下:

    #include<iostream>
    #include<cstring>
    #include<queue>
    using namespace std;
    int const N=20,M=200,inf=100000;
    int T,n,a[N][N],hd[N],nxt[M],cnt,to[M],w[M],num[N],ed=17;
    int d[N],cur[N];
    queue<int>q;
    int md(int x){if(x>8)x-=8; return x;}
    int md2(int x){if(x<=0)x+=8; return x;}
    void add(int x,int y,int f)
    {
        //printf("add(%d,%d)
    ",x,y);
        nxt[++cnt]=hd[x]; hd[x]=cnt; to[cnt]=y; w[cnt]=f;
        nxt[++cnt]=hd[y]; hd[y]=cnt; to[cnt]=x; w[cnt]=0;
    }
    bool bfs()
    {
        while(q.size())q.pop();
        memset(d,0,sizeof d);
        q.push(0); d[0]=1;
        while(q.size())
        {
            int u=q.front(); q.pop();
            for(int i=hd[u],v;i>-1;i=nxt[i])
                if(!d[v=to[i]]&&w[i])d[v]=d[u]+1,q.push(v);
        }
        return d[ed];
    }
    int dfs(int u,int f)
    {
        if(u==ed)return f;
        int res=0;
        for(int &i=cur[u],v;i>-1;i=nxt[i])
            if(d[v=to[i]]==d[u]+1&&w[i])
            {
                int k=dfs(v,min(w[i],f-res));
                res+=k; w[i]-=k; w[i^1]+=k;
                if(res==f)return f;
            }
        if(!res)d[u]=0;
        return res;
    }
    int main()
    {
        scanf("%d",&T);
        while(T--)
        {
            int lf=0;
            for(int i=1;i<=4;i++)
                for(int j=1;j<=4;j++)
                    scanf("%d",&a[i][j]),lf+=a[i][j];
            int right=max(a[1][4],max(a[2][1],max(a[3][2],a[4][3]))); 
            lf-=(a[1][4]+a[2][1]+a[3][2]+a[4][3]);
            num[1]=a[1][3]; num[2]=a[1][2]; num[3]=a[2][4]; num[4]=a[2][3];
            num[5]=a[3][1]; num[6]=a[3][4]; num[7]=a[4][2]; num[8]=a[4][1];
            cnt=-1; memset(hd,-1,sizeof hd);
            for(int i=1;i<=8;i++)add(0,i,num[i]),add(i+8,ed,num[i]);
            for(int i=1;i<=8;i++)
            {
                if(i%2)
                    add(i,md(i+4)+8,inf),add(i,md(i+3)+8,inf),add(i,md(i+1)+8,inf);//直:前直,左左,自左
                else
                    add(i,md(i+4)+8,inf),add(i,md2(i-3)+8,inf),add(i,md2(i-1)+8,inf);//左:前左,右直,自直 
            }
            int flow=0;
            while(bfs())
            {
                memcpy(cur,hd,sizeof hd);
                flow+=dfs(0,inf);
            }
            printf("%d
    ",max(lf-flow/2,right));
        }
        return 0;
    }
    View Code
  • 相关阅读:
    查询是哪个进程占用了特定端口
    (面向c#开发人员) 编写javascript的好习惯一 false 值
    onerror 事件 如何使用 onerror 事件捕获网页中的错误。(chrome、opera、safari 浏览器不支持)
    查找url里面的flag元素判断操作
    jquery 弹出窗
    向上滚动
    kissy helpcenter
    kissyAPI
    IE6 动态创建 iframe 无法显示的 bug 芒果
    图片轮换动画仿GIF
  • 原文地址:https://www.cnblogs.com/Zinn/p/15145234.html
Copyright © 2020-2023  润新知