台阶问题
分析
第
一
眼
看
到
这
题
的
时
候
就
直
接
想
用
D
f
s
模
拟
走
路
的
过
程
,
可
是
发
现
n
数
据
范
围
为
1
e
5
,
就
计
算
一
下
复
杂
度
。
接
近
O
(
2
n
)
第一眼看到这题的时候就直接想用Dfs模拟走路的过程,可是发现n数据范围为1e5,就计算一下复杂度。接近O(2^n)
第一眼看到这题的时候就直接想用Dfs模拟走路的过程,可是发现n数据范围为1e5,就计算一下复杂度。接近O(2n)
无
非
就
是
t
l
e
。
但
是
为
了
练
习
我
的
d
f
s
模
板
,
于
是
我
就
手
打
一
遍
T
l
e
的
d
f
s
,
代
码
如
下
无非就是tle。但是为了练习我的dfs模板,于是我就手打一遍Tle的dfs,代码如下
无非就是tle。但是为了练习我的dfs模板,于是我就手打一遍Tle的dfs,代码如下
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
ll cnt=0,n,k,p=100003;
void dfs(ll num){
if(num==n) {cnt++;cnt=cnt%p;return ;}
if(num>n) return ;
for(int i=1;i<=k;i++){
dfs(num+i);
}
return;
}
int main(){
scanf("%lld%lld",&n,&k);
dfs(0);
cout<<cnt<<endl;
return 0;
}
///dfs的复杂度是2^n tle
接
下
来
,
我
就
想
用
什
么
来
优
化
d
f
s
呢
?
d
p
突
然
出
现
在
我
的
脑
海
里
面
,
分
析
一
波
d
p
可
用
性
,
发
现
符
合
最
小
子
问
题
接下来,我就想用什么来优化dfs呢?dp突然出现在我的脑海里面,分析一波dp可用性,发现符合最小子问题
接下来,我就想用什么来优化dfs呢?dp突然出现在我的脑海里面,分析一波dp可用性,发现符合最小子问题
于
是
,
我
就
假
设
初
始
位
置
为
j
,
目
标
位
置
为
i
,
那
么
d
p
[
d
i
s
]
表
示
走
到
d
i
s
的
时
候
所
用
的
所
有
可
能
方
式
。
我
们
接
下
来
考
虑
于是,我就假设初始位置为j,目标位置为i,那么dp[dis]表示走到dis的时候所用的所有可能方式。我们接下来考虑
于是,我就假设初始位置为j,目标位置为i,那么dp[dis]表示走到dis的时候所用的所有可能方式。我们接下来考虑
怎
样
从
j
转
移
到
i
位
置
呢
?
怎样从j转移到i位置呢?
怎样从j转移到i位置呢?
从
j
位
置
走
到
i
位
置
,
分
j
=
i
−
k
,
i
−
(
k
−
1
)
,
i
−
(
k
−
2
)
,
.
.
.
.
.
.
,
i
−
1
这
些
位
置
走
一
步
到
达
,
那
么
我
们
就
可
以
利
用
循
环
来
更
新
d
p
[
i
]
从j位置走到i位置,分j=i-k,i-(k-1),i-(k-2),......,i-1这些位置走一步到达,那么我们就可以利用循环来更新dp[i]
从j位置走到i位置,分j=i−k,i−(k−1),i−(k−2),......,i−1这些位置走一步到达,那么我们就可以利用循环来更新dp[i]
for(int i=1;i<=n;i++){
for(int j=1;j<=k;j++){/判断条件需要修改,这里只是为了说明怎么走
dp[i]=dp[i]+dp[i-j];
}
}
细
心
的
你
可
以
发
现
当
i
小
与
等
于
k
的
时
候
会
出
现
错
误
。
没
错
,
就
是
这
样
,
这
里
我
们
就
可
以
在
上
面
的
判
断
条
件
中
改
一
下
细心的你可以发现当i小与等于k的时候会出现错误。没错,就是这样,这里我们就可以在上面的判断条件中改一下
细心的你可以发现当i小与等于k的时候会出现错误。没错,就是这样,这里我们就可以在上面的判断条件中改一下
把
j
<
=
k
把j<=k
把j<=k改成j<=k&&i-j>=0
AC
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
const int maxn=1e5+5;
int n,k,p=100003,dp[maxn];
int main(){
scanf("%d%d",&n,&k);
dp[0]=dp[1]=1;
for(int i=2;i<=n;i++){
for(int j=1;j<=k&&i-j>=0;j++){
dp[i]=(dp[i]+dp[i-j])%p;
}
}
cout<<dp[n]<<endl;
return 0;
}
备注,ll数据处理比int数据慢很多,见下图