zoukankan      html  css  js  c++  java
  • Codeforces 712D: Memory and Scores

    题目链接

    给你两个人的分数a,b
    然后两个人各自在[−k,k]之间随机等可能选,然后加到自己的分数上
    然后t轮之后,第一个人分数比第二个人高的情况,有多少种

    有一个暴力的O(k^2 t^2)的算法,很容易想到,可以利用前缀和的方法来进行优化,得到O(kt^2)的算法。

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    
    const int mod=1e9+7;
    const int mid=100000;
    
    int a,b,k,t;
    LL dp[105][200005];
    LL pre[200005];
    LL ans;
    
    int main()
    {
        cin>>a>>b>>k>>t;
        dp[0][mid]=1;
        for(int i=1; i<=t; i++)
        {
            for(int j=0; j<=mid*2; j++)
                if(dp[i-1][j])        //判断是否会产生新的方案,是的话,就打上标记,再通过求前缀和得到新的dp[i][j] 
                {
                    dp[i][j-k]=(dp[i][j-k]+dp[i-1][j])%mod;
                    dp[i][j+k+1]=(dp[i][j+k+1]-dp[i-1][j]+mod)%mod;
                }
            for(int j=1; j<=mid*2; j++)
                dp[i][j]=(dp[i][j]+dp[i][j-1])%mod;    //至此,dp[i][j]表示经过i轮之后,一个人共选分为j-mid的方案数 
        }
        pre[0]=dp[t][0];
        for(int j=1; j<=mid*2; j++)
            pre[j]=(dp[t][j]+pre[j-1])%mod;        //pre[i]记录,一个人t轮之后所得分数<=j-mid的方案总数,这是一个前缀和 
        for(int j=b-a+1; j<=2*mid; j++)
            ans=(ans+1ll*dp[t][j]*pre[min(mid*2,j-(b-a+1))])%mod;    
        cout<<ans<<endl;
    }
  • 相关阅读:
    常见的位运算技巧总结(膜wys)
    BZOJ1878:[SDOI2009]HH的项链
    BZOJ4300:绝世好题
    BZOJ1298:[SCOI2009]骰子的学问
    BZOJ2748:[HAOI2012]音量调节
    BZOJ1951:[SDOI2010]古代猪文
    BZOJ1002:[FJOI2007]轮状病毒
    BZOJ1081:[SCOI2005]超级格雷码
    BZOJ2595:[WC2008]游览计划
    BZOJ1190:[HNOI2007]梦幻岛宝石
  • 原文地址:https://www.cnblogs.com/Just--Do--It/p/7230755.html
Copyright © 2011-2022 走看看