AT2370
前言
NOIP 模拟联考题,赛时随手打了一个暴力,赛后随便想想整出个做法,发现这里没有,那就发一下吧。
思路
设当前黑白球分别有 个。
注意到这个变化过程可以在二维平面上很轻松地表现出来。
每一步形如加一个向量,则发现其实运动轨迹可以视为在一条直线上。
问题在于:如何统计答案?
我们发现,任何一个运动轨迹,只要其运动的左端点与右端点距离不超过 ,则其必然可行。
于是先设计一个 的暴力 dp:
设走了 步,当前运动所到达的最左端点与当前点距离为 ,所到达的最右端点与当前点距离为 ,此时的方案数为 。
容易写出此 dp:
A[0][0]=1; for(uint i=0;i<m;i++){ for(uint j=0;j<=n;j++)for(uint k=0;j+k<=n;k++)Last[j][k]=A[j][k],A[j][k]=0; for(uint j=0;j<=n;j++)for(uint k=0;j+k<=n;k++) { A[std::max(j,1u)][k]+=Last[j][k]; A[j][std::max(k,1u)]+=Last[j][k]; A[j?j-1:0][k+1]+=Last[j][k]; A[j+1][k?k-1:0]+=Last[j][k]; } }
然后答案即为 。
但是这个 dp 很不优美。
我们怀疑这和 的设计有关。
我们考虑设 表示走了 步,当前运动所到达的最左端点与当前点距离不大于 ,所到达的最右端点与所到达的左端点距离不大于 ,此时的方案数。
为了方便接下来推导,我们暂时忽视 这一维。
则对两个端点简单容斥得到 。
于是
我们发现,原来我们只用求出两行 即可。
但是 dp 转移方程还是太恶心了。
于是设 。
则
容易验证这个 dp 方程满足要求。
你发现 这一维在 dp 过程中是常数,于是忽视即可。
于是就得到一个 做法,滚动数组即可通过。
然而似乎可以做的更好?
注意到这个转移方程中 之间的贡献关系写到二维平面上形如格路计数的形式。
于是使用反射容斥法即可算出单点点值,总复杂度为 ,由于 时答案显然 ,所以就是 啦!
Code
以下是 dp 部分代码。
typedef AnyMod::ModInt modint; modint A[6005],Last[6005]; int main(){ #ifdef MYEE freopen("QAQ.in","r",stdin); #endif uint n,m;scanf("%u%u",&n,&m);AnyMod::ChgMod(1e9+7); for(uint i=0;i<=n*2;i+=2)A[i]=1; for(uint i=1;i<=m*2;i++)for(uint j=i&1;j<=n*2;j+=2) { A[j]=0; if(j)A[j]+=A[j-1]; if(j<(n*2))A[j]+=A[j+1]; } modint ans; for(uint i=0;i<=n*2;i+=2)ans+=A[i]; for(uint i=0;i<=n*2-2;i+=2)A[i]=1; for(uint i=1;i<=m*2;i++)for(uint j=i&1;j<=n*2-2;j+=2) { A[j]=0; if(j)A[j]+=A[j-1]; if(j<(n*2-2))A[j]+=A[j+1]; } for(uint i=0;i<=n*2-2;i+=2)ans-=A[i]; ans.println(); return 0; }
本文来自博客园,作者:myee,转载请注明原文链接:https://www.cnblogs.com/myee/p/Luogu-solution-AT2370.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 2025年我用 Compose 写了一个 Todo App
· 张高兴的大模型开发实战:(一)使用 Selenium 进行网页爬虫