题解 P3266 【[JLOI2015]骗我呢】
Peanut_Tang · · 题解
[JLOI2015]骗我呢
更好的阅读体验:https://www.cnblogs.com/peanuttang/p/14389554.html
简要题意
给定
对于任意的
结果对
题解
第
我们发现,一行只有
于是我们设计 DP 状态
考虑转移,发现如果
再优化一下:
答案就是
我们考虑这个式子的组合意义,我们先将它映射到坐标轴上。下图中箭头表示转移,而答案就是从
这里面有些转移时“斜”的,这不太直观。我们将这个网格图变换一下,将第
我们在
我们发现答案就是从
如果没有两条直线的限制,那么答案显然就是
我们回想一下初中奥数“将军饮马”问题,我们发现将
这样我们就可以计算了。容斥一下,答案就是
预处理阶乘的复杂度是线性的;而对称过程,每次的对称距至少增加
Code
#include <bits/stdc++.h>
#define il inline
#define ll long long
const int N=3e6+5,P=1e9+7;
int n,m,fac[N],ans;
il int ksm(int a,int b){int res=1; for ( ; b; b>>=1,a=(ll)a*a%P) if (b&1) res=(ll)res*a%P; return res;}
il int C(int x,int y){return x<0||y<0?0:(ll)fac[x+y]*ksm(fac[x],P-2)%P*ksm(fac[y],P-2)%P;}
il void trans(int &x,int &y,int a){std::swap(x,y),x-=a,y+=a;}
int main()
{
scanf("%d%d",&n,&m); int i,x,y;
for (i=fac[0]=1; i<N; i++) fac[i]=(ll)fac[i-1]*i%P;
for (x=n+m+1,y=n,ans=C(x,y); x>=0&&y>=0;) trans(x,y,1),ans=(ans-C(x,y)+P)%P,trans(x,y,-m-2),ans=(ans+C(x,y))%P;
for (x=n+m+1,y=n; x>=0&&y>=0; ) trans(x,y,-m-2),ans=(ans-C(x,y)+P)%P,trans(x,y,1),ans=(ans+C(x,y))%P; printf("%d\n",ans);
return 0;
}