BZOJ 3782: 上学路 Lucas+ExCRT+容斥+dp
其实呢,扩展中国剩余定理还有一种理解方式:就是你有一坨东西,形如:
$A[i]\equiv B[i](mod$ $P[i])$.
对于这个东西,你可以这么思考:
如果最后能求出一个解,那么这个解的增量一定是 $lcm(P[1],P[2].....).$
所以,只要你能找到一坨 $P[i]$,使得它们的 $lcm$ 等于你想要的东西,你就可以用 $excrt$来解.
p话扯完了,我们步入正题:
假设没有障碍,有 $n$ 行 $m$ 列,那么答案即为 $C_{n+m}^{n}.$
这个东西就代表你一共会走 $n+m$ 步,其中 $n$ 步的方向是向上的.
而如果有障碍,我们考虑按照每一个障碍点一次枚举.
首先,将障碍按照横纵坐标从小到大拍一个序,那么考虑我们枚举到第 $i$ 个障碍.
令 $f[i]$ 表示从起点到第 $i$ 个障碍所走过的合法的方案数,$(x,y)$ 表示横纵坐标.
总方案为 $C_{x+y}^{y},$ 不合法的方案为 $\sum f[前面障碍]$.
如果随便减的话,我们可能减多,所以我们考虑按照策略去减.
我们想让每一次减掉的都互不相同,所以我们考虑枚举第一个不合法的障碍.
即 $C_{x+y}^{y}-\sum_{j=1}^{i-1}f[j]\times calc(j到i的方案数).$
这样,我们等于说是强制性的每次只减掉第一个障碍碰到 $j$ 的方案数,不会减多.
这个题的模数不是素数,所以需要将模数分解成若干个素数,然后依次取模,最后在用 $excrt$ 合并.
Code:
#include <cstdio>
#include <algorithm>
#define N 1000006
#define ll long long
#define setIO(s) freopen(s".in","r",stdin)
using namespace std;
ll F[N];
int array[10]={0,3,5,6793,10007};
struct Node {
ll x,y;
Node(ll x=0,ll y=0):x(x),y(y){}
}arr[N];
bool cmp(Node a,Node b) {
return a.x==b.x?a.y<b.y:a.x<b.x;
}
ll qpow(ll base,ll k,ll mod) {
ll tmp=1;
for(;k;k>>=1,base=base*base%mod)
if(k&1) tmp=tmp*base%mod;
return tmp;
}
struct Lucas {
int mod;
int fac[N];
int inv(int i) {
return (int)qpow(i,mod-2,mod);
}
void init(int p) {
mod=p,fac[0]=1;
for(int i=1;i<=mod;++i) fac[i]=(ll)fac[i-1]*i%mod;
}
int C(int x,int y) {
if(y>x) return 0;
if(y==0) return 1;
return (int)(1ll*fac[x]*inv(fac[y])%mod*inv(fac[x-y])%mod);
}
int solve(ll x,ll y) {
if(y>x) return 0;
if(y==0) return 1;
return (int)(1ll*solve(x/mod,y/mod)*C(x%mod,y%mod)%mod);
}
}comb[8];
struct excrt {
ll arr[N],brr[N];
ll exgcd(ll a,ll b,ll &x,ll &y) {
if(!b) {
x=1,y=0;
return a;
}
ll gcd=exgcd(b,a%b,x,y),tmp=x;
x=y,y=tmp-a/b*y;
return gcd;
}
ll Excrt() {
int i,j;
ll ans=arr[1],M=brr[1];
for(i=2;i<=4;++i) {
ll a=M,b=brr[i],c=arr[i]-ans,gcd,x,y;
gcd=exgcd(a,b,x,y),b=abs(b/gcd);
x=(x*(c/gcd)%b+b)%b;
ans+=M*x;
M*=brr[i]/__gcd(brr[i],M);
ans=(ans%M+M)%M;
}
return ans;
}
}crt;
ll C(ll a,ll b,int ty) {
if(ty==0)
return comb[0].solve(a,b);
else {
int i,j;
for(i=1;i<=4;++i) {
crt.arr[i]=comb[i].solve(a,b);
crt.brr[i]=array[i];
}
}
return crt.Excrt();
}
int main() {
int i,j,k,flag;
// setIO("input");
ll n,m,mod;
scanf("%lld%lld%d%lld",&n,&m,&k,&mod),flag=(mod==1019663265);
if(!flag) {
comb[0].init(mod);
}
else {
for(i=1;i<=4;++i)
comb[i].init(array[i]);
}
for(i=1;i<=k;++i)
scanf("%lld%lld",&arr[i].x,&arr[i].y);
arr[++k].x=n,arr[k].y=m;
sort(arr+1,arr+1+k,cmp);
for(i=1;i<=k;++i) {
F[i]=C(arr[i].x+arr[i].y,arr[i].y,flag);
for(j=1;j<i;++j) {
if(arr[j].y<=arr[i].y)
F[i]=(F[i]-(F[j]*C(arr[i].x-arr[j].x+arr[i].y-arr[j].y,arr[i].y-arr[j].y,flag)%mod)+mod)%mod;
}
}
printf("%lld\n",F[k]);
return 0;
}
BZOJ 3782: 上学路 Lucas+ExCRT+容斥+dp的更多相关文章
- bzoj 3782 上学路线 卢卡斯定理 容斥 中国剩余定理 dp
LINK:上学路线 从(0,0)走到(n,m)每次只能向上或者向右走 有K个点不能走求方案数,对P取模. \(1\leq N,M\leq 10^10 0\leq T\leq 200\) p=10000 ...
- BZOJ 3782: 上学路线 [Lucas定理 DP]
3782: 上学路线 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 192 Solved: 75[Submit][Status][Discuss] ...
- bzoj3782上学路线(Lucas+CRT+容斥DP+组合计数)
传送门:https://www.lydsy.com/JudgeOnline/problem.php?id=3782 有部分分的传送门:https://www.luogu.org/problemnew/ ...
- HDU 5794 A Simple Chess (容斥+DP+Lucas)
A Simple Chess 题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5794 Description There is a n×m board ...
- $bzoj2560$ 串珠子 容斥+$dp$
正解:容斥+$dp$ 解题报告: 传送门$QwQ$ $umm$虽然题目蛮简练的了但还是有点难理解,,,我再抽象一点儿,就说有$n$个点,点$i$和点$j$之间有$a_{i,j}$条无向边可以连,问有多 ...
- [CF1086E]Beautiful Matrix(容斥+DP+树状数组)
给一个n*n的矩阵,保证:(1)每行都是一个排列 (2)每行每个位置和上一行对应位置不同.求这个矩阵在所有合法矩阵中字典序排第几.考虑类似数位DP的做法,枚举第几行开始不卡限制,那么显然之前的行都和题 ...
- 【BZOJ3622】已经没有什么好害怕的了 容斥+DP
[BZOJ3622]已经没有什么好害怕的了 Description Input Output Sample Input 4 2 5 35 15 45 40 20 10 30 Sample Output ...
- BZOJ.4767.两双手(组合 容斥 DP)
题目链接 \(Description\) 棋盘上\((0,0)\)处有一个棋子.棋子只有两种走法,分别对应向量\((A_x,A_y),(B_x,B_y)\).同时棋盘上有\(n\)个障碍点\((x_i ...
- BZOJ 2005 [Noi2010]能量采集 (数学+容斥 或 莫比乌斯反演)
2005: [Noi2010]能量采集 Time Limit: 10 Sec Memory Limit: 552 MBSubmit: 4493 Solved: 2695[Submit][Statu ...
随机推荐
- [LGP4707] 重返现世
世界是物质的,物质是运动的,运动是有规律的,规律是可以被认识的. 关于期望意义下min-max容斥,我们认为每个事件的时间来认识事件,max/min S表示集合S中所有时间最后/最前出现的事件,E(m ...
- Invoker(小DP)
题意:http://acm.hdu.edu.cn/showproblem.php?pid=6739 尽量让他们连起来. 思路: 直接dp,其中一个状态是以什么结尾. #define IOS ios_b ...
- 关于python中的包,模块导入的问题详解(二)
from import导入 紧接着的是from xx import xx 语法 1 ################ 2 from my_moudule import name 3 print(na ...
- python私有化xx、_xx、__xx、__xx__、xx_的区别
xx:共有变量. _xx:私有化的属性或方法,from xxx import * 时无法导入,子类的对象和子类可以访问. __xx:避免与子类中的属性命名冲突,无法在外部直接访问(名字重整所以访问不到 ...
- fio安装使用
# wget http://brick.kernel.dk/snaps/fio-2.2.5.tar.gz # tar xvf fio-2.2.5.tar.gz# cd fio-2.2.5# ./con ...
- Vue 表情输入组件,微信face表情组件
VUE表情包输入组件,先来张成品图看看. 年底了没事干,把以前做过的项目中的组件拿出来再复习一下, 先说说思路吧. 注意: 1. 项目是用vue-cli3.0搭建起来的项目, 参考cli3.0官网地址 ...
- Linux磁盘挂载、分区、扩容操作
本文最早发布于 Rootrl's blog 注:以下操作系统环境为CentOS7 基本概念 在操作前,首先要了解一些基本概念 磁盘 在Linux系统中所有的设备都会以文件的形式存储.设备一般保存在/d ...
- 杭电2019多校第一场,Problem I,String 2019
题目描述 Tom has a string containing only lowercase letters. He wants to choose a subsequence of the str ...
- Q_OBJECT提供了信号槽机制、国际化机、RTTI 的反射能力(cpp中使用Q_OBJECT导致无法处理moc,就需要#include “moc_xxx.h”)
只有继承了QObject类的类,才具有信号槽的能力.所以,为了使用信号槽,必须继承QObject.凡是QObject类(不管是直接子类还是间接子类),都应该在第一行代码写上Q_OBJECT.不管是不 ...
- webpack编写一个plugin插件
插件向第三方开发者提供了 webpack 引擎中完整的能力.使用阶段式的构建回调,开发者可以引入它们自己的行为到 webpack 构建流程中.创建插件比创建 loader 更加高级,因为你将需要理解一 ...