1 条题解
-
0
自动搬运
来自洛谷,原作者为

xiaoliebao1115
real life搬运于
2025-08-24 23:00:58,当前版本为作者最后更新于2024-08-11 16:37:18,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
大佬写的题解都太抽象了,这一篇题解献给每一个蒟蒻们。
朴素动态规划
从左到右进行动态规划即可,就是 ,这里的 都有一条从 出发的火车路径经停 ,特别的 。
文中的 就表示的是从维尔纽斯开始到 结束的方案数总和,这个应该都能理解。最后 。
根号分治
情况
先令 ,很容易发现对于 的情况来讲最多只有 个位置可以从当前位置转移,总复杂度 。
情况
考虑 的情况,注意到这里的 的种类数最多不会超过 个。所以我们开一个数组 表示最后经过一个 的路线到达 的总方案数,注意,这个数组只记录 的情况。
我们可以得到一些转移方程:,这个表示把这条 的铁路线继续往下一个站点开。
,这里的 已经保存了 的所有答案,加上剩余部分即可。
,这个表示一条从 开始的铁路线, 就是第一个停下来的地方,通过向这个地方转移,可以让 根据前面的式子向后面停下来的位置转移。
但是考虑到从一个地方开始的火车经停站数量有限,所以有 ,因为从 往后就不能再停车了,正确性是显然的,相当于把 这个式子中增加的 给减掉,有点类似于差分的思路。
这边的每次转移都是 ,并且 大小是 的,所以整个程序总时间复杂度 。
code
#include<bits/stdc++.h> using namespace std; #define int long long const int nn=1e5+5,B=317,mod=1e9+7; int n,f[nn][B],dp[nn],ans; signed main(){ ios::sync_with_stdio(0),cin.tie(0),cout.tie(0); cin>>n; int b=sqrt(n); dp[1]=1; for(int i=1;i<=n;i++){ int d,x; cin>>d>>x; for(int j=1;j<=b;j++){ if(i+j<=n) f[i+j][j]=(f[i+j][j]+f[i][j])%mod; dp[i]=(dp[i]+f[i][j])%mod; } ans=(ans+dp[i])%mod; if(d==0) continue; if(d>b){ for(int j=i+d,k=1;j<=n&&k<=x;j+=d,k++) dp[j]=(dp[i]+dp[j])%mod; } else{ if(i+d<=n) f[i+d][d]=(f[i+d][d]+dp[i])%mod; if(i+d*(x+1)<=n) f[i+d*(x+1)][d]=(f[i+d*(x+1)][d]-dp[i]+mod)%mod; } } cout<<ans<<endl; return 0; }这里需要注意的是在 或者是超出范围的时候要特判一下,记得赋初值。
- 1
信息
- ID
- 10527
- 时间
- 1000ms
- 内存
- 512MiB
- 难度
- 5
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者