这个题目背景真的是让我想起了当年。。。

不说了,言归正传,这题,一眼看去30分暴力还是很好拿的,但我因为考试时的心态问题没有处理好细节爆了零。

30分暴力的普遍思路的复杂度应该是$O(nmd)$的,但是d的数据范围实在恐怖,根本无法AC。

30分思路看上去优化空间不是很大(但是有神犇想出了矩阵快速幂加速转移,TQL)。

我们考虑转换一下思路,首先d肯定是不能放进复杂度里的,那又要怎么转移呢,我们观察到因为最多有n块饼干,所以最多真正给她饼干的天数也就是n天,那么我们根据这个来设计状态:设$f[i][j]$表示真正给她$i$天,给了$j$块饼干的方案总数。那么我们可以的出状态转移方程即为$f[i][j]=\Sigma_{k=j-m}^{j-1}{f[i-1][k]}$,

$ans=\Sigma{f[i][n]*C_d^i}$。还是很好理解的趴,但是我们现在的dp式子的复杂度依然是$O(n^3)$的,考虑优化,后面的式子是一个区间和的形式,这样就很容易想到前缀和优化。复杂度就变成了$O(n^2)$。

还有就是这题要注意的几点:首先是d太大无法用我们平常用的方式求出,最好是将组合数公式展开约分求解。

             其次就是在第二层循环里,本来应该是枚举$j$从$i$到$i*(m-1)$,但是前缀和要处理到$n$,因为你的前缀和是要为下一层服务的,而下一层很可能要用到$n$,所以前缀和一定要处理到$n$。

优化dp的题之前还是做的不多,这题也算练练吧。

 #include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
#include<vector>
#define int long long
#define ll long long
using namespace std;
const int N=;
const int mod=;
int dp[N][N],sum[N][N],inv[N];
int qpow(int a,int b){
int ans=;
a%=mod;
while(b){
if(b&) ans=ans*a%mod;
b>>=;
a=a*a%mod;
}
return ans;
}
/*inline int C(int a,int b){
int js=1ll,facd=1ll;
for(register int i=1;i<=b;i++) js=(js*i)%mod;
for(register int i=a-b+1;i<=a;i++) {facd=i%mod*facd%mod;cout<<"L"<<facd<<endl;}
return facd*qpow(js,mod-2)%mod;
}*/
/*inline int C(int x,int y){
int facd=1ll,faci=1ll;
x%=mod;
for(register int i=2;i<=x;++i) faci=(faci*i)%mod;
for(register int i=y-x+1;i<=y;++i) facd=i%mod*facd%mod;
int inv=qpow(faci,mod-2);
//printf("%lld %lld %lld\n",faci,facd,inv);
return facd*inv%mod;
}*/
int C(int y,int x){
if(y<0ll||x<0ll||y<x)return ;
y%=mod;
if(y==0ll||x==0ll)return ;
ll ans=;
for(int i=0ll;i<x;i++)
ans=ans*(y-i)%mod;
for(int i=1ll;i<=x;i++)
ans=ans*inv[i]%mod;
return ans;
}
signed main(){
int n,m,d;
for(int i=1ll;i<=2000ll;i++)
inv[i]=qpow(i,mod-2ll);
while(~scanf("%lld%lld%lld",&n,&d,&m)){
if(!n&&!m&&!d) break;
if(n>d*(m-)) {puts("");continue;}
memset(dp,,sizeof(dp));
memset(sum,,sizeof(sum));
for(int i=;i<m;i++){
dp[][i]=;
sum[][i]=dp[][i]+sum[][i-];
}
for(int i=m;i<=n;i++) sum[][i]=sum[][i-];
int ans=;
ans+=(dp[][n]*C(d,1ll))%mod;
for(int i=;i<=min(d,n);i++){
for(int j=i;j<=n;j++){
dp[i][j]=((sum[i-][j-]-sum[i-][max(j-m,0ll)])%mod+mod)%mod;
sum[i][j]=(sum[i][j-]+dp[i][j])%mod;
//cout<<dp[i][j]<<endl;
}
ans=(ans+dp[i][n]*C(d,i)%mod)%mod;
}
//cout<<dp[1][n]<<endl;
//for(int i=2;i<=min(d,n);i++) ans=(ans+dp[i][n]*C(d,i)%mod)%mod;
printf("%lld\n",ans%mod);
}
}

HZOJ 20190719 那一天我们许下约定(dp+组合数)的更多相关文章

  1. HZOI2019 A. 那一天我们许下约定 dp

    题目大意:https://www.cnblogs.com/Juve/articles/11219089.html 读这道题的题目让我想起了... woc我到底在想什么?好好写题解,现在不是干那个的时候 ...

  2. NOIP模拟测试6「那一天我们许下约定(背包dp)·那一天她离我而去」

    那一天我们许下约定 内部题,题干不粘了. $30分算法$ 首先看数据范围,可以写出来一个普通dp #include<bits/stdc++.h> #define ll int #defin ...

  3. HZOJ 那一天我们许下约定

    比较好想的一道题,只是那个组合数比较恶心. 先说一下我最开始想的$n^4$的沙雕dp: 设f[i][j][k]为前i天给了j个,第i天给了k个,则f[i][j][k]=∑f[i-1][j-k][o]; ...

  4. [CSP-S模拟测试]:那一天我们许下约定(DP+组合数学)

    题目传送门(内部题2) 输入格式 每个测试点有多组测试数据.对于每组数据,有一行共三个整数$N$,$D$,$M$含义如题.输入结束标识为$“0 0 0”$ (不含引号). 输出格式 对于每组数据,输出 ...

  5. 【模拟7.19】那一天我们许下约定(组合数学,DP)

    看了题目名字深切怀疑出题人是不是失恋了,然后出题折磨我们.然后这题就愉快的打了个暴力,最后莫名其妙wa20,伤心..... 其实这题正解不是很难想,如果说把暴力的DP搞出来,正解也差不到哪去了, 我们 ...

  6. 一文读懂AI简史:当年各国烧钱许下的愿,有些至今仍未实现

    一文读懂AI简史:当年各国烧钱许下的愿,有些至今仍未实现 导读:近日,马云.马化腾.李彦宏等互联网大佬纷纷亮相2018世界人工智能大会,并登台演讲.关于人工智能的现状与未来,他们提出了各自的观点,也引 ...

  7. HZOJ 20190719 那一天她离我而去(图论最小环)

    这题算是这场考试里最水的一道题了吧,就是求个最小环,但之前没练过,就在考场上yy出了最短路+次短路的傻逼解法,首先是不会求次短路,其次是这显然不对呀,自己随便想想就可以反驳这种解法. 正解比较神,但是 ...

  8. 两个约束下的dp问题

    洛谷P1510 分析:本质上还是一个01背包,将体力当做重量,体积当做价值.配上滚动数组 即dp[j]代表在体力耗费为j时最大能搬运多少体积的石头,当dp[j]>v时就说明存在满足情况的解,这样 ...

  9. 首次使用windows管理界面访问安装在UNIX或linux下的DP服务器时提示无权限访问的解决方法

    用windwos GUI管理界面连接时提示无权限访问: 在/etc/opt/omni/server/users/userlist 添加一行: "" "*" &q ...

随机推荐

  1. sqlalchemy定义mysql时间戳字段

    update_time = Column(TIMESTAMP, nullable=False, comment='更新时间戳', server_default=text('CURRENT_TIMEST ...

  2. Java 封装与类

    一.面向对象编程 面向对象编程三大特性:封装.继承和多态. 类是实现封装的手段,是面向对象编程的基本单元. 封装隐藏了类的内部实现细节,暴露给外界可控的操作,提高数据的完整性和安全性,提高模块的可重用 ...

  3. 怎样理解HTMLCollection接口

    和 NodeList 类似, HTMLCollection 也是一个 类数组对象, 和NodeList不同的是, 它是各种 元素节点 的集合, 且不具有 forEach() 方法, 因此如果不转为真正 ...

  4. PMP - 风险识别之风险登记册

    目录 PMP - 风险识别之风险登记册 1. 风险登记册 1.1 已识别风险的清单 1.2 潜在风险责任人 1.3 潜在风险应对措施清单 2. 相关习题 2.1 风险发生的时候,要实施 风险登记册 上 ...

  5. shiro学习(二)

    自定义realm(主要就是自定义的realm要继承AuthorizingRealm 类,重写两个方法(一是认证,而是授权,两个方法一般要查询数据库,这里用的是模拟数据) ) public class ...

  6. day09 并发编程

    一. 目录 1.进程的概念和两种创建方式 2.多进程爬虫 3.守护进程 4.进程队列 5.进程队列简单应用(实现数据共享) 6.线程的两种创建方式 7.线程和进程的效率对比 8.线程共享统一进程的数据 ...

  7. 描述Cookie和Session的作用,区别和各自的应用范围,Session工作原理

    Session用于保存每个用户的专用信息. 每个客户端用户访问时,服务器都为每个用户分配一个唯一的会话ID(Session ID) . 她的生存期是用户持续请求时间再加上一段时间(一般是20分钟左右) ...

  8. 7.Struts2拦截器及源码分析

    1.Struts2架构图 2.Struts2 执行过程分析 1.首先,因为使用 struts2 框架,请求被Struts2Filter 拦截 2.Struts2Filter  调用 DisPatche ...

  9. yii2-cache组件第三个参数Dependency $dependency的作用浅析

    用法如下: $cache->set($key, $result, Configs::instance()->cacheDuration, new TagDependency([ 'tags ...

  10. webpack初体验_集成插件_集成loader

    webpack初体验 如果没装 webpack 就先装一下,命令行输入npm i webpack -g 新建一个项目 创建一个空的项目 定义一个名称 创建一个Module 选择静态 web 输入名称 ...