题解:P3266 [JLOI2015] 骗我呢
题意
有一个
的数组 ,满足:
求可能的数组
的解数,答案对 取模。
分析
首先根据
又因为
考虑使用 dp。
令
模拟过程可得若第
所以得到转移方程:
答案即为
转移过程如下(
我们将这个图像拉伸,平移一下:
发现就是求从
考虑使用反射容斥。
由容斥得:答案为总方案数 - 经过
考虑如何计算每一部分。
已知从点
总方案数为原点到到
经过
经过
将
方案数即为原点到
若某次对称得到的点
Code
#include<bits/stdc++.h> using namespace std; #define mod 1000000007 #define maxn 4000006 int pre[maxn], inv[maxn]; int64_t ksm(int64_t x, int l) { int64_t ret=1; for(;l;l>>=1, x=x*x%mod) if(l&1) ret=ret*x%mod; return ret; } int C(int n, int m) {return ((int64_t)pre[n]*inv[n-m]%mod)*inv[m]%mod;} typedef pair<int, int> pos_t; int path_count(pos_t p) {return C(p.first+p.second, p.first);} pos_t reflect(int a, pos_t p) {return {p.second-a, a+p.first};} int reflect(int a, int b) {return (a<<1)-b;} int main() { pre[0]=1; for(int i=1;i<maxn;i++) pre[i]=(int64_t)pre[i-1]*i%mod; inv[maxn-1]=ksm(pre[maxn-1], mod-2); for(int i=maxn-2;~i;i--) inv[i]=(int64_t)inv[i+1]*(i+1)%mod; int n, m; cin>>n>>m; int a1=2, a2=-m-1; int mul=-1, ans=path_count({n+m-1, n}); for(pos_t p=reflect(a1, {n+m-1, n});p.first>=0&&p.second>=0;) { ans=((ans+mul*path_count(p))%mod+mod)%mod; a2=reflect(a1, a2); swap(a1, a2); p=reflect(a1, p); mul*=-1; } mul=-1; a1=-m-1, a2=2; for(pos_t p=reflect(a1, {n+m-1, n});p.first>=0&&p.second>=0;) { ans=((ans+mul*path_count(p))%mod+mod)%mod; a2=reflect(a1, a2); swap(a1, a2); p=reflect(a1, p); mul*=-1; } cout<<ans; }
本文作者:Jimmy-LEEE
本文链接:https://www.cnblogs.com/redacted-area/p/18379561
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步