1 条题解
-
0
自动搬运
来自洛谷,原作者为

huayucaiji
I was once great.The glory is bound to be back one day!搬运于
2025-08-24 22:10:08,当前版本为作者最后更新于2021-03-21 08:51:23,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
其实这个题蛮简单的。
作为一个国家抬杠二级运动员,我们要杠一下这句话:
请注意,上述背景内容与本题无关!
我非要让你有关考虑普通的过河卒,若没有马(不是骂人),那么从 ,的方案数是 。其意义是,我总共走 步,其中 步向上,选出这 步的位置就是方案数。
现在我们还可以沿着斜对角走,我们枚举斜着走的方案数:
$$ans=\sum\limits_{i=0}^{\min(n,m)} C_{n+m-i}^i\cdot C_{n+m-2*i}^{n-i} $$我们回归题目,题目现在是 。题目里说:
其次,过河卒二的终点不再是一个特定的位置,Kiana 规定卒可以从棋盘的上方或右方走出棋盘,此时就视为游戏成功。注意在走出棋盘时仍然有方向选择的不同。
我们可以认为是从 呀,理解为加上一行一列。
但是现在还有一个疑难没解决,就是障碍的问题。可以用容斥原理来计算。但是时间会炸。可以先预处理。我们对每个障碍按横坐标排序,排序后计算出任意两个之间方案数,带入公式:
由于模数是质数,可以用
Lucas定理解决。//Don't act like a loser. //This code is written by huayucaiji //You can only use the code for studying or finding mistakes //Or,you'll be punished by Sakyamuni!!! #include<bits/stdc++.h> #define int long long using namespace std; int read() { char ch=getchar(); int f=1,x=0; while(ch<'0'||ch>'9') { if(ch=='-') f=-1; ch=getchar(); } while(ch>='0'&&ch<='9') { x=x*10+ch-'0'; ch=getchar(); } return f*x; } const int MAXN=1e5+10,MOD=59393; int n,m,k; int jc[MAXN],f[21][21],invjc[MAXN]; struct point { int x,y; }p[21]; bool cmp(point a,point b) { if(a.x!=b.x) { return a.x<b.x; } return a.y<b.y; } int qpow(int x,int y) { int ret=1; while(y) { if(y&1) { ret=ret*x%MOD; } x=x*x%MOD; y>>=1; } return ret; } int inv(int x) { return qpow(x,MOD-2); } int C(int x,int y) { if(y>x) { return 0; } return jc[x]*invjc[y]%MOD*invjc[x-y]%MOD; } int lucas(int x,int y) { if(y==0) { return 1; } return lucas(x/MOD,y/MOD)*C(x%MOD,y%MOD)%MOD; } int fff(int n,int m) { if(min(n,m)<0) { return 0; } int ret=0,ub=min(n,m); for(int i=0;i<=ub;i++) { ret=(ret+lucas(n+m-i,i)*lucas(n+m-i*2,n-i)%MOD)%MOD; } return ret; } int calc(int s) { if(!(s&(1<<0))||!(s&(1<<k))) { return 0; } int lst[22]={},cnt=0,times=1; for(int i=0;i<=k;i++) { if(s&(1<<i)) { lst[++cnt]=i; times=times*-1; } } times=(times+MOD)%MOD; for(int i=2;i<=cnt;i++) { times=times*f[lst[i-1]][lst[i]]%MOD; } return times; } signed main() { jc[0]=1; invjc[0]=1; for(int i=1;i<=MOD;i++) { jc[i]=jc[i-1]*i%MOD; invjc[i]=inv(jc[i]); } cin>>n>>m>>k; n++; m++; for(int i=1;i<=k;i++) { p[i].x=read(); p[i].y=read(); } p[0].x=1;p[0].y=1; k++; p[k].x=n; p[k].y=m; sort(p+1,p+k+1,cmp); for(int i=0;i<=k;i++) { for(int j=i+1;j<=k;j++) { f[i][j]=fff(p[j].x-p[i].x,p[j].y-p[i].y); } } int ans=0; for(int i=0;i<(1<<k+1);i++) { ans=(ans+calc(i))%MOD; } cout<<ans<<endl; return 0; }
- 1
信息
- ID
- 4362
- 时间
- 1000ms
- 内存
- 500MiB
- 难度
- 6
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者