3782: 上学路线

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 192  Solved: 75
[Submit][Status][Discuss]

Description

小C所在的城市的道路构成了一个方形网格,它的西南角为(0,0),东北角为(N,M)。小C家住在西南角,学校在东北角。现在有T个路口进行施工,小C不能通过这些路口。小C喜欢走最短的路径到达目的地,因此他每天上学时都只会向东或北行走;而小C又喜欢走不同的路径,因此他问你按照他走最短路径的规则,他可以选择的不同的上学路线有多少条。由于答案可能很大,所以小C只需要让你求出路径数mod P的值。

Input

第一行,四个整数N、M、T、P。
接下来的T行,每行两个整数,表示施工的路口的坐标。

Output

一行,一个整数,路径数mod P的值。

HINT

1<=N,M<=10^10
0<=T<=200
p=1000003或p=1019663265

终于A掉了
这道题太可怕了
跟PoPoQQQ大爷的代码拍了好几组数据才改完Bug
 
首先想怎么算方案数
总-不合法
用容斥原理?好麻烦
发现一个点只会对$x,y$都比它大的点产生影响
$f[i]$表示走到点$i$不碰到其他点的方案数
$f[i]={x_i+y_i\choose x_i} - \sum\limits_{x_j<=x_i\ ,\ y_j<=y_i\ ,\ j\neq i}{x_i-x_j+y_i-y_j\choose x_i-x_j}*f[j] $
 
剩下的就是怎么计算组合数了
1000003直接用Lucas定理
1019663265和古代猪文一样是4个质数的乘积,Lucas定理+CRT合并
 
说一下问题:
1.DP时要时刻记住取模、
2.小心n和m溢出int
3.组合数n<m特判在用Lucas定理的时候不能丢!因为模意义下可能发生n<m!!!
 
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
typedef long long ll;
const int N=1e6+;
inline ll read(){
char c=getchar();ll x=,f=;
while(c<''||c>''){if(c=='-')f=-;c=getchar();}
while(c>=''&&c<=''){x=x*+c-'';c=getchar();}
return x*f;
}
ll n,m,P;
int t;
struct Point{
ll x,y;
bool operator <(const Point &a)const{
return x<a.x||(x==a.x&&y<a.y);
}
}a[];
namespace A{
ll P=;
ll inv[N],fac[N],facInv[N];
void ini(){
inv[]=fac[]=facInv[]=;
for(int i=;i<=P;i++){
if(i!=) inv[i]=-P/i*inv[P%i]%P;
inv[i]+=inv[i]<?P:;
fac[i]=fac[i-]*i%P;
facInv[i]=facInv[i-]*inv[i]%P;
}
}
ll C(int n,int m){
if(n<m) return ;
return fac[n]*facInv[m]%P*facInv[n-m];
}
ll Lucas(ll n,ll m){
if(n<m) return ;
ll re=;
for(;m;n/=P,m/=P) re=re*C(n%P,m%P)%P;
return re;
}
ll f[];
void dp(){
for(int i=;i<=t;i++){
f[i]=Lucas(a[i].x+a[i].y,a[i].x);//printf("fo %d %lld\n",i,f[i]);
for(int j=;j<i;j++)
if(a[j].x<=a[i].x&&a[j].y<=a[i].y)
f[i]=(f[i]- Lucas(a[i].x-a[j].x+a[i].y-a[j].y,a[i].x-a[j].x)*f[j]%P +P)%P;
//printf("oh %d %lld %lld \n",j ,Lucas(a[i].x-a[j].x+a[i].y-a[j].y,a[i].x-a[j].x)*f[j]%P ,f[i]);
//printf("f %d %lld\n",i,f[i]);
}
}
void solve(){
ini();
dp();
printf("%lld",f[t]);
}
}
namespace B{
ll P[]={,,,,};
const int N=1e5+;
ll Pow(ll a,ll b,ll P){
if(a==) return ;
ll re=;
for(;b;b>>=,a=a*a%P)
if(b&) re=re*a%P;
return re;
}
ll Inv(ll a,ll P){return Pow(a,P-,P);}
ll inv[N][],fac[N][],facInv[N][];
void ini(){
for(int j=;j<=;j++){
int MOD=P[j];
inv[][j]=fac[][j]=facInv[][j]=;
for(int i=;i<=MOD;i++){
if(i!=) inv[i][j]=-MOD/i*inv[MOD%i][j]%MOD;
if(inv[i][j]<) inv[i][j]+=MOD;
fac[i][j]=fac[i-][j]*i%MOD;
facInv[i][j]=facInv[i-][j]*inv[i][j]%MOD;
}
}
}
ll C(int n,int m,int j){//printf("C %d %d %d %lld %lld\n",n,m,j,fac[n][j],facInv[m][j]);
if(n<m) return ;
ll p=P[j];
return fac[n][j]*facInv[m][j]%p*facInv[n-m][j]%p;
}
ll lucas(ll n,ll m,int j){
if(n<m) return ;
ll MOD=P[],a=,p=P[j];
for(;m;m/=p,n/=p) a=a*C(n%p,m%p,j)%p;
return a*(MOD/p)%MOD*Inv(MOD/p,p)%MOD;
}
ll Lucas(ll n,ll m){//printf("Lucas1 %lld %lld\n",n,m);
ll re=,MOD=P[];
for(int i=;i<=;i++)
re=(re+lucas(n,m,i))%MOD;
return re;
} ll f[];
void dp(){
for(int i=;i<=t;i++){
f[i]=Lucas(a[i].x+a[i].y,a[i].x);//printf("fo %d %lld\n",i,f[i]);
for(int j=;j<i;j++)
if(a[j].x<=a[i].x&&a[j].y<=a[i].y)
f[i]=(f[i]- Lucas(a[i].x-a[j].x+a[i].y-a[j].y,a[i].x-a[j].x)*f[j]%P[] +P[])%P[];
//printf("oh %d %lld %lld \n",j ,Lucas(a[i].x-a[j].x+a[i].y-a[j].y,a[i].x-a[j].x)*f[j] ,f[i]);
// printf("fn %d %lld\n",i,f[i]);
}
}
void solve(){
ini();
dp();
//for(int i=1;i<=t;i++)
// printf("Point %lld %lld %lld\n",a[i].x,a[i].y,f[i]);
printf("%lld",f[t]);
}
}
int main(){
freopen("in","r",stdin);
n=read();m=read();
t=read();P=read();
for(int i=;i<=t;i++) a[i].x=read(),a[i].y=read();
a[++t].x=n;a[t].y=m;
sort(a+,a++t);
if(P==) A::solve();
else B::solve();
}
 
 
 

BZOJ 3782: 上学路线 [Lucas定理 DP]的更多相关文章

  1. bzoj 3782 上学路线 卢卡斯定理 容斥 中国剩余定理 dp

    LINK:上学路线 从(0,0)走到(n,m)每次只能向上或者向右走 有K个点不能走求方案数,对P取模. \(1\leq N,M\leq 10^10 0\leq T\leq 200\) p=10000 ...

  2. BZOJ 3782 上学路线 ——动态规划 Lucas定理 中国剩余定理

    我们枚举第一个经过的坏点,然后DP即可. 状态转移方程不是难点,难点在于组合数的处理. 将狼踩尽的博客中有很详细的证明过程,但是我只记住了结论 $n=a_1 * p^k+a_2*p^k-1...$ $ ...

  3. BZOJ 3782: 上学路 Lucas+ExCRT+容斥+dp

    其实呢,扩展中国剩余定理还有一种理解方式:就是你有一坨东西,形如:$A[i]\equiv B[i](mod$ $P[i])$. 对于这个东西,你可以这么思考:如果最后能求出一个解,那么这个解的增量一定 ...

  4. BZOJ 3782 上学路线

    首先这个题需要dp.dp[i]=C(x[i]+y[i],x[i])-Σdp[j]*C(x[i]-x[j]+y[i]-y[j],x[i]-x[j])(x[i]>=x[j],y[i]>=y[j ...

  5. bzoj 1902: Zju2116 Christopher lucas定理 && 数位DP

    1902: Zju2116 Christopher Time Limit: 1 Sec  Memory Limit: 64 MBSubmit: 172  Solved: 67[Submit][Stat ...

  6. [CTSC2017]吉夫特(Lucas定理,DP)

    送70分,预处理组合数是否为偶数即可. 剩下的数据,根据Lucas定理的推论可得当且仅当n&m=n的时候,C(n,m)为奇数.这样就可以直接DP了,对于每个数,考虑它对后面的数的影响即可,直接 ...

  7. 洛谷P3773 [CTSC2017]吉夫特(Lucas定理,dp)

    题意 满足$b_1 < b_2 < \dots < b_k$且$a_{b_1} \geqslant a_{b_2} \geqslant \dots \geqslant a_{b_k} ...

  8. Bzoj 4403: 序列统计 Lucas定理,组合数学,数论

    4403: 序列统计 Time Limit: 3 Sec  Memory Limit: 128 MBSubmit: 328  Solved: 162[Submit][Status][Discuss] ...

  9. BZOJ - 2142 礼物 (扩展Lucas定理)

    扩展Lucas定理模板题(貌似这玩意也只能出模板题了吧~~本菜鸡见识鄙薄,有待指正) 原理: https://blog.csdn.net/hqddm1253679098/article/details ...

随机推荐

  1. c语言基础学习09_关于复合类型的复习

    =============================================================================struct A{ char array[10 ...

  2. PHP安全之webshell和后门检测

    基于PHP的应用面临着各种各样的攻击: XSS:对PHP的Web应用而言,跨站脚本是一个易受攻击的点.攻击者可以利用它盗取用户信息.你可以配置Apache,或是写更安全的PHP代码(验证所有用户输入) ...

  3. 基于 fireasy 构建的 asp.net core 示例

    最近花时间弄了一个关于fireasy使用的demo,已放到 github 上供大家研究,https://github.com/faib920/zero 该 demo 演示了如何使用 fireasy 创 ...

  4. .24-浅析webpack源码之事件流compilation(2)

    下一个compilation来源于以下代码: compiler.apply(new EntryOptionPlugin()); compiler.applyPluginsBailResult(&quo ...

  5. Oracle_rowid_rownum分页

      Oracle_rowid_rownum_分页 --rowid select * from account where rowid='AAASR6AAEAAAAJWAAA';       selec ...

  6. 版本控制——TortoiseSVN (1)安装与配置

    =================================版权声明================================= 版权声明:原创文章 禁止转载  请通过右侧公告中的“联系邮 ...

  7. Asp.net mvc 中的路由

    在 Asp.net mvc 中,来自客户端的请求总是针对某个 Controller 中的 Action 方法,因此,必须采用某种机制从请求的 URl 中解析出对应的 Controller 和 Acti ...

  8. VisualSFM+PMVS生成稠密点云

    利用相机拍摄一个场景不同角度的图片,使用VisualSFM能够得到稀疏点云,如果想要得到稠密点云,可以在VisualSFM中加入PMVS的应用程序,PMVS会作为一个插件运行将稀疏点云插成稠密的点云. ...

  9. sql子查询

    一.子查询入门: 1.单值子查询: 单值子查询的唯一限制:子查询的返回值必须只有一行记录,而且只能有一列(又被称为标量子查询). 可以使用在select语句的列表.表达式中,以及where语句中等. ...

  10. 让我们一起爱(装)上Homestead吧

    本文是Laravel实战:任务管理系统(一)的扩展阅读原文链接 先来点残酷现实:  真正用过homestead的,一般不会问homestead到底好在哪里 如果你还没有爱上homestead,只能说明 ...