Memory and Scores

题目链接:http://codeforces.com/contest/712/problem/D

dp

因为每轮Memory和Lexa能取的都在[-k,k],也就是说每轮两人分数的变化量在[-2k,2k];

故可以定义状态:dp[times][diff]为第times次Memory和Lexa的分数差为diff的方案数.

而dp[times][diff]可以从dp[times-1][diff-2k]到dp[times-1][diff+2k]转移而来;

又因为变化量为-2k时的方案数为1(-k,k),

变化量为-2k+1时的方案数为2(-k,k-1;-k+1,k),

变化量为-2k+2时的方案数为3(-k,k-2;-k+1,k-1;-k+2,k),

...,

变化量为-2k+m时的方案数为m+1,

...,

变化量为0时的方案数为2k+1,

...,

变化量为2k-m时的方案数为m+1,

...,

变化量为2k-1时的方案数为2,

变化量为2k时的方案数为1.

所以状态转移方程为:dp[times][diff]=dp[times-1][diff-2k]+2*dp[times-1][diff-2k+1]+3*dp[times-1][diff-2k+2]+...+(m+1)*dp[times-1][diff-2k+m]+...+2*dp[times-1][diff+2k-1]+dp[times-1][diff+2k];

这样的话,时间复杂度为O(k2t2),代码如下:

 #include<iostream>
#include<cmath>
#define M 1000000007LL
#define TIME 105
#define DIFF 300000
#define BASE 150000
using namespace std;
typedef long long LL;
LL a,b,k,t,ans;
LL dp[TIME][DIFF];
int main(void){
cin>>a>>b>>k>>t;
dp[][a-b+BASE]=;
LL upper=a-b+BASE+*k*t;
LL lower=a-b+BASE-*k*t;
for(LL times=;times<=t;++times){
for(LL diff=lower;diff<=upper;diff++){
for(LL m=;m<=*k;m++){
LL add=-*k+m;
if(diff+add>=lower){
if(add)dp[times][diff]+=(dp[times-][diff+add]+dp[times-][diff-add])*(m+);
else dp[times][diff]+=dp[times-][diff]*(m+);
dp[times][diff]%=M;
}
}
}
}
for(int i=BASE+;i<=upper;++i)
ans=(ans+dp[t][i])%M;
cout<<ans<<endl;
}

很显然,这会T,所以必须做出优化。

注意到:

dp[times][diff]是在dp[times][diff-1]的基础上前半段各个项减一,后半段各个项加一得到的,所以可以维护一个前缀和数组pre[i],那么

dp[times][diff]=dp[times][diff-1]+(pre[diff+2k]-pre[diff-1])-(pre[diff-1]-pre[(diff-1)-2k-1])

可以在O(1)的时间内完成,优化后的代码时间复杂度为O(kt2),代码如下:

 #include<iostream>
#include<cmath>
#define M 1000000007LL
#define TIME 105
#define DIFF 500000
#define BASE 250000
using namespace std;
typedef long long LL;
LL a,b,k,t,ans;
LL dp[TIME][DIFF];
LL pre[DIFF];
int main(void){
cin>>a>>b>>k>>t;
dp[][a-b+BASE]=;
LL upper=a-b+BASE+*k*t;
LL lower=a-b+BASE-*k*t;
for(LL times=;times<=t;++times){
for(LL diff=lower;diff<=upper;diff++)
pre[diff]=pre[diff-]+dp[times-][diff],pre[diff]%=M;
for(LL m=;m<=*k;m++){
LL add=-*k+m;
if(add)dp[times][lower]
+=(dp[times-][lower+add]+dp[times-][lower-add])*(m+);
else dp[times][lower]+=dp[times-][lower]*(m+);
dp[times][lower]%=M;
}
for(LL diff=lower+;diff<=upper;diff++){
dp[times][diff]=dp[times][diff-]
+(pre[min(upper,diff+*k)]-pre[diff-])
-(pre[diff-]-pre[max(lower,diff--*k)-]);
dp[times][diff]=(dp[times][diff]+M)%M;
//记得+M,减法模运算可能会出现负数
}
}
for(int i=BASE+;i<=upper;++i)
ans=(ans+dp[t][i])%M;
cout<<ans<<endl;
}

这样的代码仍然可以优化:

1.可以用滚动数组来优化空间复杂度,从O(kt2)降低到O(kt),太懒没写╮(╯▽╰)╭;

2.可以用快速傅里叶变换FFT优化时间复杂度,从O(kt2)继续降到O(kt lg(kt)),没学还不会写╮(╯▽╰)╭

//昨天去面试微软俱乐部被嘲讽=。= 定个目标吧,这学期div2稳定4题怎么样?

Memory and Scores的更多相关文章

  1. Codeforces Round #370 (Div. 2) D. Memory and Scores DP

    D. Memory and Scores   Memory and his friend Lexa are competing to get higher score in one popular c ...

  2. Codeforces Round #370 (Div. 2) D. Memory and Scores 动态规划

    D. Memory and Scores 题目连接: http://codeforces.com/contest/712/problem/D Description Memory and his fr ...

  3. [Codeforces712D] Memory and Scores(DP+前缀和优化)(不用单调队列)

    [Codeforces712D] Memory and Scores(DP+前缀和优化)(不用单调队列) 题面 两个人玩游戏,共进行t轮,每人每轮从[-k,k]中选出一个数字,将其加到自己的总分中.已 ...

  4. 【26.87%】【codeforces 712D】Memory and Scores

    time limit per test2 seconds memory limit per test512 megabytes inputstandard input outputstandard o ...

  5. [CodeForces - 712D]Memory and Scores (DP 或者 生成函数)

    题目大意: 两个人玩取数游戏,第一个人分数一开始是a,第二个分数一开始是b,接下来t轮,每轮两人都选择一个[-k,k]范围内的整数,加到自己的分数里,求有多少种情况使得t轮结束后a的分数比b高.  ( ...

  6. Codeforces 712 D. Memory and Scores (DP+滚动数组+前缀和优化)

    题目链接:http://codeforces.com/contest/712/problem/D A初始有一个分数a,B初始有一个分数b,有t轮比赛,每次比赛都可以取[-k, k]之间的数,问你最后A ...

  7. CodeForces 712D Memory and Scores

    $dp$,前缀和. 记$dp[i][j]$表示$i$轮结束之后,两人差值为$j$的方案数. 转移很容易想到,但是转移的复杂度是$O(2*k)$的,需要优化,观察一下可以发现可以用过前缀和来优化. 我把 ...

  8. CF370 D Memory and Scores

    dp题 并运用了前缀和 我看题目提示中有fft 我想了下感觉复杂度不过关还是未解 #include<bits/stdc++.h> using namespace std; typedef ...

  9. CF712D Memory and Scores

    题目分析 实际上两个人轮流取十分鸡肋,可以看作一个人取2t次. 考虑生成函数. 为了方便,我们对取的数向右偏移k位. 取2t次的生成函数为: \[ F(x)=(\sum_{i=0}^{2k}x_i)^ ...

随机推荐

  1. 删除style的样式JQuery

      有些页面样式不规范,没有写在一个class里,例如:<div id="show" style="width:100px; padding-top:10px; f ...

  2. Java实践 — SSH远程执行Shell脚本(转)

    原文地址:http://www.open-open.com/lib/view/open1384351384024.html 1. SSH简介         SSH是Secure Shell的缩写,一 ...

  3. C++-----lambda使用

    lambda是匿名函数,可以拿来当作inline函数使用(用于解决程序员的"起名困难综合症") lambda函数形式: [...] (...) ... {...} [] 内是一个c ...

  4. 转载一篇nm命令使用的文章,虽然没用用这个方法解决但是文章很好

    http://blog.csdn.net/acs713/article/details/13505931

  5. [SQL基础教程] 4-2 数据删除(DELETE)

    [SQL基础教程] C4 数据更新 4-2 数据删除(DELETE) DROP TABLE / DELETE DROP TABLE - 完全删除表 DELETE - 仅删除数据,保留表容器 DELET ...

  6. 关于AVL实现的代码记录

    试题集合: https://www.patest.cn/contests/pat-a-practise/1064 https://www.patest.cn/contests/pat-a-practi ...

  7. redis整合spring

    最近公司项目有用到     所以找了一下实例.感觉很清晰.    完整项目路径http://www.cnblogs.com/dennisit/p/3614521.html看了一下应该没问题

  8. JavaScript忍者秘籍——闭包

    概要:本篇博客主要介绍了JavaScript的闭包 1.闭包的工作原理 简单地说,闭包就是一个函数在创建时允许该自身函数访问并操作该自身函数之外的变量时所创建的作用域. 例如: var outerVa ...

  9. seajs +gruntjs 合作开发

    nodejs的出现 让服务器端能运行 js commonjs规范 规范服务器端开发按照什么写法去写 包括模块化开发 ( 不同点 请求在本地 js加载) AMD规范 浏览器端开发的规范 (不同点: 浏览 ...

  10. Mysql的热备份[转载]

    学一点 mysql 双机异地热备份----快速理解mysql主从,主主备份原理及实践 双机热备的概念简单说一下,就是要保持两个数据库的状态自动同步.对任何一个数据库的操作都自动应用到另外一个数据库,始 ...