interlinkage:
https://jzoj.net/senior/#contest/show/2703/3
description:
solution:
考虑容斥原理,枚举不合法的走的步数
$f_{p,x,y}$表示任意走$p$步走到$x$,$y$的方案数
$g_{p,x}$表示走不合法的步走$p$步走到$(10*x,10*x)$的方案数
$g$数组很好得到,发现$f$数组直接暴力转移时间复杂度不对
但是随意走在横轴和竖轴上是独立的,因此我们可以设$fx_{p,x}$表示在横轴上走$p$步走到位置$x$的方案数,同理得到$fy$数组
$f_{p,x,y}=fx_{p,x}*fy_{p,y}$
那么$ans=sum_{i=0}^{R}dbinom{R}{i}sum_{z=0}^{min(Tx,Ty)/10}g_{i,z}*f_{R-i,Tx-10*z,Ty-10*z}$
注意因为零向量不可走,方便处理我们将它加入不可走的数组中即可,因为$0 mod 10=0$也是成立的
code:
#include<iostream> #include<cstring> #include<cstdio> #include<cmath> #include<algorithm> using namespace std; typedef long long ll; const int M=1600+15; const int mo=1e4+7; int Tx,Ty,Mx,My,R,K; int fx[M][M],fy[M][M],sum[M],kk[M],g[M][M],C[M][M]; int main() { freopen("jump.in","r",stdin); freopen("jump.out","w",stdout); scanf("%d%d%d%d%d%d",&Tx,&Ty,&Mx,&My,&R,&K); for (int j=0;j<=Tx;j++) sum[j]=1; for (int i=1;i<=R;i++) { for (int j=0;j<=Tx;j++) { if (j>Mx) fx[i][j]=((sum[j]-sum[j-Mx-1])%mo+mo)%mo; else fx[i][j]=sum[j]; } sum[0]=fx[i][0]; for (int j=1;j<=Tx;j++) sum[j]=(sum[j-1]+fx[i][j])%mo; } for (int j=0;j<=Ty;j++) sum[j]=1; for (int i=1;i<=R;i++) { for (int j=0;j<=Ty;j++) { if (j>My) fy[i][j]=((sum[j]-sum[j-My-1])%mo+mo)%mo; else fy[i][j]=sum[j]; } sum[0]=fy[i][0]; for (int j=1;j<=Ty;j++) sum[j]=(sum[j-1]+fy[i][j])%mo; } for (int i=1;i<=K;i++) scanf("%d",&kk[i]);kk[++K]=0; g[0][0]=1; for (int k=1;k<=R;k++) { for (int i=0;10*i<=min(Tx,Ty);i++) { for (int j=1;j<=K;j++) if (i>=kk[j]/10) { (g[k][i]+=g[k-1][i-kk[j]/10])%=mo; } } } C[0][0]=1; for (int i=1;i<=R;i++) { C[i][0]=1; for (int j=1;j<=i;j++) C[i][j]=(C[i-1][j-1]+C[i-1][j])%mo; } int ans=0; for (int i=0;i<=R;i++) { if (i&1) { for (int z=0;z*10<=min(Tx,Ty);z++) (ans-=1ll*C[R][i]*g[i][z]%mo*fx[R-i][Tx-10*z]%mo*fy[R-i][Ty-10*z]%mo)%=mo; } else { for (int z=0;z*10<=min(Tx,Ty);z++) (ans+=1ll*C[R][i]*g[i][z]%mo*fx[R-i][Tx-10*z]%mo*fy[R-i][Ty-10*z]%mo)%=mo; } } ans=(ans%mo+mo)%mo; printf("%d ",ans); return 0; }