传送门
神题
O
r
z
Orz
Orz。
先预处理出三个 d p dp dp数组:
f x i , j fx_{i,j} fxi,j表示横向不加限制走 i i i步走到 j j j的方案数。
f y i , j fy_{i,j} fyi,j表示纵向不加限制走 i i i步走到 j j j的方案数。
f i , j f_{i,j} fi,j表示走 i i i步每次只能走被限制的步数最终走 j j j格方案数。
然后就可以xjb容斥就能算出答案。
显然可以枚举走几步非法的得出答案。
代码:
#include<bits/stdc++.h>
#define ri register int
using namespace std;
const int rlen=1<<18|1;
inline char gc(){
static char buf[rlen],*ib,*ob;
(ib==ob)&&(ob=(ib=buf)+fread(buf,1,rlen,stdin));
return ib==ob?-1:*ib++;
}
inline int read(){
int ans=0;
char ch=gc();
while(!isdigit(ch))ch=gc();
while(isdigit(ch))ans=((ans<<2)+ans<<1)+(ch^48),ch=gc();
return ans;
}
const int mod=1e4+7;
inline int add(const int&a,const int&b){return a+b>=mod?a+b-mod:a+b;}
inline int dec(const int&a,const int&b){return a>=b?a-b:a-b+mod;}
inline int mul(const int&a,const int&b){return a*b>=mod?a*b-a*b/mod*mod:a*b;;}
inline void Add(int&a,const int&b){a=a+b>=mod?a+b-mod:a+b;}
inline void Dec(int&a,const int&b){a=a>=b?a-b:a-b+mod;}
inline void Mul(int&a,const int&b){a=a*b>=mod?a*b-a*b/mod*mod:a*b;}
const int N=1605,M=805;
class FoxJumping{
public:
int R,K,n,m,a,b,fx[N][M],fy[N][M],f[N][M],C[N][N],ss[M],ban[55],mx=0;
inline int getsum(int l,int r){return dec(ss[r],l?ss[l-1]:0);}
int Main(){
for(ri i=0;i<=R;++i){
C[i][0]=C[i][i]=1;
for(ri j=1;j<i;++j)C[i][j]=add(C[i-1][j-1],C[i-1][j]);
}
fx[0][0]=1;
for(ri i=0;i<=n;++i)ss[i]=1;
for(ri i=1;i<=R;++i){
for(ri j=0;j<=n;++j)fx[i][j]=getsum(max(j-a,0),j);
for(ri j=0;j<=n;++j)ss[j]=add(j?ss[j-1]:0,fx[i][j]);
}
fy[0][0]=1;
for(ri i=0;i<=m;++i)ss[i]=1;
for(ri i=1;i<=R;++i){
for(ri j=0;j<=m;++j)fy[i][j]=getsum(max(j-b,0),j);
for(ri j=0;j<=m;++j)ss[j]=add(j?ss[j-1]:0,fy[i][j]);
}
f[0][0]=1;
for(ri i=1;i<=R;++i){
for(ri j=0,up=min(mx*i,min(n,m));j<=up;j+=10){
for(ri k=1;k<=K;++k){
if(ban[k]>j)continue;
Add(f[i][j],f[i-1][j-ban[k]]);
}
}
}
int ans=0;
for(ri i=0,t=0;i<=R;++i,t=0){
for(ri up=min(i*mx,min(n,m)),j=0;j<=up;j+=10)Add(t,mul(f[i][j],mul(fx[R-i][n-j],fy[R-i][m-j])));
Mul(t,C[R][i]);
i&1?Dec(ans,t):Add(ans,t);
}
return ans;
}
inline int getCount(int n_, int m_, int a_, int b_, int R_,vector<int>t){
n=n_,m=m_,a=a_,b=b_,R=R_,K=t.size();
bool ff=0;
for(ri i=1;i<=K;++i)ff|=(ban[i]=t[i-1])==0,mx=max(mx,ban[i]);
if(!ff)ban[++K]=0;
return Main();
}
};