• Codeforces Round #370 (Div. 2)


    A - Memory and Crow

    这题我没看题意,看了样例猜了一下就AC了,题目好像还挺复杂的。

    #include<bits/stdc++.h>
    using namespace std;
    int a[100005];
    int main()
    {
        int n;
        cin>>n;
        for(int i=1;i<=n;i++) scanf("%d",&a[i]);
        for(int i=1;i<n;i++) printf("%d ",a[i]+a[i+1]);
        printf("%d
    ",a[n]);
        return 0;
    }
    View Code

     B - Memory and Trident

    题目大意:一个人可以往上下左右走,给你一串操作,问你最少改变几个能回到原地。

    思路:将上下分成一堆,左右分成一堆,改变的时候优先同一堆里面的互换。这样能

    保证次数最少。代码写的有点搓。

    #include<bits/stdc++.h>
    using namespace std;
    const int N=1e5+5;
    char s[N];
    int vis[4];
    int main()
    {
        scanf("%s",s);
        int len=strlen(s);
        if(len%2)
        {
            puts("-1");
            return 0;
        }
        for(int i=0;i<len;i++)
        {
            if(s[i]=='U') vis[0]++;
            else if(s[i]=='D') vis[1]++;
            else if(s[i]=='L') vis[2]++;
            else vis[3]++;
        }
        if((vis[0]+vis[1])%2==0)
        {
            int a=(vis[0]+vis[1])/2-min(vis[0],vis[1]);
            int b=(vis[2]+vis[3])/2-min(vis[2],vis[3]);
            cout<<a+b<<endl;
        }
        else
        {
            int a=(vis[0]+vis[1]-1)/2-min(vis[0],vis[1]);
            //cout<<a<<endl;
            int b=(vis[2]+vis[3]-1)/2-min(vis[2],vis[3]);
            cout<<a+b+1<<endl;
        }
        return 0;
    }
    View Code

    C - Memory and De-Evolution

    题目大意:给你两个边长分别为x和y的等边三角形,问你最少通过多少次改变可以把x变成y(x>y)

    每次改变可以改变一条边,且改变后三边依旧能构成三角形。

    思路:想了一会就想出来了,反过来模拟,从y模拟到x,每次y都取出最小的边把它变成能变成

    的最大值,等到最小的边都大于x了就结束。

    #include<bits/stdc++.h>
    using namespace std;
    int x,y;
    int a[3];
    int main()
    {
        cin>>x>>y;
        a[0]=a[1]=a[2]=y;
        int i=0;
        int ans=0;
        for(;;i++)
        {
            ans++;
            a[i%3]=a[(i+1)%3]+a[(i+2)%3]-1;
            //printf("%d %d %d
    ",a[0],a[1],a[2]);
            if(min(a[(i+1)%3],a[(i+2)%3])>=x) break;
        }
        cout<<ans<<endl;
        return 0;
    }
    View Code

    D - Memory and Scores

    题目大意:两个人有初试分数a和b,有 t  轮游戏,每轮游戏每人随机得到[-k,k]中的一个数加

    到自己的分数中,问你k轮以后,有多少个结果是 第一个人得分数大于第二个人的。结果对1e9+7取模。

    思路:用dp[i][j] 表示进行到 i 轮,分数为得到的分数为j 的方案数。

    状态转移方程,dp[i][j]=dp[i-1] [j-k]+dp[i-1][j-k+1]+...+dp[i-1][j+k]。

    直接这样写可能会超时,我们考虑用前缀和优化,即每一轮更新

    的时候保存当前轮dp的前缀和,用于更新下一轮。最后就是计算

    方案总数的问题了。

    #include<bits/stdc++.h>
    #define ll long long
    using namespace std;
    const int N=2*1e5+1;
    ll dp[101][N],a[N],b[N];
    ll x,y,k,t;
    const ll mod=1e9+7;
    int main()
    {
        cin>>x>>y>>k>>t;
        ll up=k*t*2;
        dp[0][k*t]=1;
        for(ll i=0;i<=up;i++)
        {
            if(i==0) a[i]=dp[0][i];
            else a[i]=a[i-1]+dp[0][i];
        }
        ll *p=a,*q=b,*g;
        for(ll i=1;i<=t;i++)
        {
            for(ll j=0;j<=up;j++)
            {
                ll l=j-k,r=j+k;
                l=max((ll)0,l);r=min(up,r);
                ll t=dp[i][j];
                if(l==0) dp[i][j]=(dp[i][j]+p[r])%mod;
                else dp[i][j]=(dp[i][j]+p[r]-p[l-1]+mod)%mod;
                if(j==0) q[j]=dp[i][j]%mod;
                else q[j]=(dp[i][j]+q[j-1])%mod;
            }
            g=q;
            q=p;
            p=g;
        }
        ll ans=0;
        ll dis=y-x+1;
        for(ll i=0;i<=up;i++)
        {
            ll now=i-dis;
            if(now>up) now=up;
            if(now>=0) ans=(ans+((dp[t][i])*p[now])%mod)%mod;
        }
    
        cout<<ans%mod<<endl;
        return 0;
    }
    View Code

    E - Memory and Casinos

    题目大意:有n个赌场,每个赌场你赢的概率为p,如果赢了你往右边的赌场走,输了往左边的赌场走,

    给你一个范围 l 到 r 问你从 l 开始,最后在 r 赢且不在 l 输的概率是多少,写的时候真的不知道怎么写。。

    还是太菜了。

    思路:我们可以用线段树进行区间合并,我们记L( l , r )为从 l 开始最后在r赢不在且在 l 永远不输的概率,

    R( l , r )为从 r 开始,最后在 r 赢,且永远不在 l 输的概率。我们对线段树的每个节点保存当前区间的这

    两个值,每个节点保存该区间的 L 和 R 值。那么两个区间该如何合并呢?

    我们可以先考虑只有两个点的情况 a 点和 b 点,求从 a 开始,最终在 b 点赢,且在 a 点永远不输的概率,

    且 在 a 点赢的概率为p1,b 点为 p2,那么我们可以知道我们要求的概率就是一下式子的和

    p1*p2         a(win)   b(win)

    p1 * ( ( 1 - p2 ) * p1 ) * p2        a(win) b(lose) a(win) b(win)

    p1 * ( ( 1 - p2 ) * p1)^2 * p2     a(w) ( b(l)  a(w)  b(l)  a(w) ) b(w)

    .............

    p1 * ( ( 1 - p2 ) * p1)^n * p2

    求和就是等比数列求和。

    那么对于两个区间也是同理,对于两个区间a,b,他们的L,R分别为  L1 , L2 , R1  R2,合并之后的 L 为 L3  R 为 R3

    那么 L3 为以下式子的和

    L1 * L2

    L1 * ( ( 1 - L2 ) * R1 ) * L2

    L1 * ( ( 1 - L2 ) * R1 )^2  * L2

    ............

    L1 * ( ( 1 - L2 ) * R1 ) ^n * L2

    R3 为以下式子的和

    R2

    ( 1 - R2 ) * R1 * L2

    ( 1 - R2 ) * R1 *( ( 1 - L2 ) * R1 ) * L2

    ( 1 - R2 ) * R1 *( ( 1 - L2 ) * R1 )^2 * L2

    .............

    ( 1 - R2 ) * R1 *( ( 1 - L2 ) * R1 )^n * L2

    这样就能完成线段树的区间合并了。

    #include<bits/stdc++.h>
    #define pdd pair<double,double>
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    #define fi first
    #define se second
    #define ls rt<<1
    #define rs rt<<1|1
    using namespace std;
    const int N=1e5+5;
    pdd st[N<<2];
    int n,q;
    pdd Merge(pdd x,pdd y)
    {
        pdd ans;
        ans.fi=(x.fi*y.fi)/(1.0-x.se*(1.0-y.fi));
        ans.se=y.se+((1.0-y.se)*x.se*y.fi)/(1.0-(1.0-y.fi)*x.se);
        return ans;
    }
    void build(int l,int r,int rt)
    {
        if(l==r)
        {
            double a,b;
            scanf("%lf%lf",&a,&b);
            st[rt].fi=a/b; st[rt].se=a/b;
            return;
        }
        int m=(l+r)>>1;
        build(lson);
        build(rson);
        st[rt]=Merge(st[ls],st[rs]);
    }
    void updata(int l,int r,int rt,int x,double a,double b)
    {
        if(l==r && r==x)
        {
            st[rt].fi=a/b;st[rt].se=a/b;
            return;
        }
        int m=(l+r)>>1;
        if(x<=m) updata(lson,x,a,b);
        else updata(rson,x,a,b);
        st[rt]=Merge(st[ls],st[rs]);
    }
    pdd query(int L,int R,int l,int r,int rt)
    {
        if(l>=L && r<=R) return st[rt];
        int m=(l+r)>>1;
        if(R<=m) return query(L,R,lson);
        else if(L>m) return query(L,R,rson);
        else return Merge(query(L,R,lson),query(L,R,rson));
    }
    int main()
    {
        cin>>n>>q;
        build(1,n,1);
        while(q--)
        {
            int op;
            scanf("%d",&op);
            if(op==1)
            {
                int  x;
                double a,b;
                scanf("%d%lf%lf",&x,&a,&b);
                updata(1,n,1,x,a,b);
            }
            else
            {
                int l,r;
                scanf("%d%d",&l,&r);
                pdd ans=query(l,r,1,n,1);
                printf("%.12f
    ",ans.fi);
            }
        }
        return 0;
    }
    View Code
  • 相关阅读:
    HDFS架构原理
    Hadoop集群搭建
    解决8080端口号占用问题
    基于SSM的Maven项目(Redis和Mysql)配置文件整合
    maven 集成SSM项目配置文件模版
    初识Spring笔记
    初识Mybatis一些总结
    将对数据库的增删改查封装为方法
    10分钟安装Elasticsearch
    ThreadLocal详解
  • 原文地址:https://www.cnblogs.com/CJLHY/p/7240669.html
Copyright © 2020-2023  润新知