传送门
题解:
设 f [ i ] [ x ] [ y ] f[i][x][y] f[i][x][y]表示用 i i i个任意向量走到 ( x , y ) (x,y) (x,y)的方案数, g [ i ] [ k ] g[i][k] g[i][k]表示用 i i i个非法向量走到 k ∗ 10 , k ∗ 10 k*10,k*10 k∗10,k∗10的方案数。
DP发现, f [ i ] [ x ] [ y ] f[i][x][y] f[i][x][y]中 x x x和 y y y的两维没有关系,分开DP,前缀和优化一下。
感觉直接并不好处理,禁用 0 0 0,允许少于 R R R步。
然后随便枚举非法步数容斥一下就行了,实际上就是算了个前缀和。
代码:
#include<bits/stdc++.h>
#define ll long long
#define re register
#define cs const
cs int mod=1e4+7;
inline int add(int a,int b){return (a+=b)>=mod?a-mod:a;}
inline int dec(int a,int b){return (a-=b)<0?a+mod:a;}
inline int mul(int a,int b){ll r=(ll)a*b;return r>=mod?r%mod:r;}
inline int power(int a,int b){int res=1;
for(;b;b>>=1,a=mul(a,a))(b&1)&&(res=mul(res,a));
return res;
}
inline void Inc(int &a,int b){(a+=b)>=mod&&(a-=mod);}
inline void Dec(int &a,int b){(a-=b)<0&&(a+=mod);}
class FoxJumping{
private:
static cs int R=1.6e3+9,M=857;
int fx[R][M],fy[R][M];
int g[R][M/10];
int fac[R],ifac[R];
int C(int n,int m){return (n>=0&&m>=0&&n>=m)?mul(fac[n],mul(ifac[m],ifac[n-m])):0;}
int F(int i,int x,int y){return mul(dec(fx[i][x+1],fx[i][x]),dec(fy[i][y+1],fy[i][y]));}
public:
FoxJumping(){}
inline int getCount(int Tx,int Ty,int Mx,int My,int R,std::vector<int> bad){
fac[0]=fac[1]=ifac[0]=1;
for(int re i=2;i<=R;++i)fac[i]=mul(fac[i-1],i);
ifac[R]=power(fac[R],mod-2);
for(int re i=R-1;i;--i)ifac[i]=mul(ifac[i+1],i+1);
int lim=std::min(Tx,Ty)/10;
g[0][0]=1;bad.push_back(0);
for(int &v:bad)v/=10;
for(int re i=1;i<=R;++i){
for(int re v:bad){
for(int re j=lim;j>=v;--j)Inc(g[i][j],g[i-1][j-v]);
}
}
for(int re i=1;i<=Tx+1;++i)fx[0][i]=1;
for(int re i=1;i<=R;++i){
for(int re j=1;j<=Tx+1;++j)
fx[i][j]=add(fx[i][j-1],dec(fx[i-1][j],fx[i-1][j-std::min(j-1,Mx)-1]));
}
for(int re i=1;i<=Ty+1;++i)fy[0][i]=1;
for(int re i=1;i<=R;++i){
for(int re j=1;j<=Ty+1;++j)
fy[i][j]=add(fy[i][j-1],dec(fy[i-1][j],fy[i-1][j-std::min(j-1,My)-1]));
}
int ans=0;
for(int re i=0;i<=R;++i){
int coef=(i&1)?mod-C(R,i):C(R,i);
for(int re j=0;j<=lim;++j)
Inc(ans,mul(coef,mul(g[i][j],F(R-i,Tx-j*10,Ty-j*10))));
}
return ans;
}
};
#ifdef zxyoi
#define gc getchar
FoxJumping Solver;
inline int getint(){
char c;
while(!isdigit(c=gc()));int num=c^48;
while(isdigit(c=gc()))num=(num+(num<<2)<<1)+(c^48);
return num;
}
int Tx,Ty,Mx,My,R,K;
std::vector<int> vec;
signed main(){
freopen("FoxJumping.in","r",stdin);
Tx=getint(),Ty=getint(),Mx=getint(),My=getint(),R=getint(),K=getint();
while(K--)vec.push_back(getint());
std::cout<<Solver.getCount(Tx,Ty,Mx,My,R,vec);
return 0;
}
#endif