其实呢,扩展中国剩余定理还有一种理解方式:就是你有一坨东西,形如:
$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:

  1. #include <cstdio>
  2. #include <algorithm>
  3. #define N 1000006
  4. #define ll long long
  5. #define setIO(s) freopen(s".in","r",stdin)
  6. using namespace std;
  7. ll F[N];
  8. int array[10]={0,3,5,6793,10007};
  9. struct Node {
  10. ll x,y;
  11. Node(ll x=0,ll y=0):x(x),y(y){}
  12. }arr[N];
  13. bool cmp(Node a,Node b) {
  14. return a.x==b.x?a.y<b.y:a.x<b.x;
  15. }
  16. ll qpow(ll base,ll k,ll mod) {
  17. ll tmp=1;
  18. for(;k;k>>=1,base=base*base%mod)
  19. if(k&1) tmp=tmp*base%mod;
  20. return tmp;
  21. }
  22. struct Lucas {
  23. int mod;
  24. int fac[N];
  25. int inv(int i) {
  26. return (int)qpow(i,mod-2,mod);
  27. }
  28. void init(int p) {
  29. mod=p,fac[0]=1;
  30. for(int i=1;i<=mod;++i) fac[i]=(ll)fac[i-1]*i%mod;
  31. }
  32. int C(int x,int y) {
  33. if(y>x) return 0;
  34. if(y==0) return 1;
  35. return (int)(1ll*fac[x]*inv(fac[y])%mod*inv(fac[x-y])%mod);
  36. }
  37. int solve(ll x,ll y) {
  38. if(y>x) return 0;
  39. if(y==0) return 1;
  40. return (int)(1ll*solve(x/mod,y/mod)*C(x%mod,y%mod)%mod);
  41. }
  42. }comb[8];
  43. struct excrt {
  44. ll arr[N],brr[N];
  45. ll exgcd(ll a,ll b,ll &x,ll &y) {
  46. if(!b) {
  47. x=1,y=0;
  48. return a;
  49. }
  50. ll gcd=exgcd(b,a%b,x,y),tmp=x;
  51. x=y,y=tmp-a/b*y;
  52. return gcd;
  53. }
  54. ll Excrt() {
  55. int i,j;
  56. ll ans=arr[1],M=brr[1];
  57. for(i=2;i<=4;++i) {
  58. ll a=M,b=brr[i],c=arr[i]-ans,gcd,x,y;
  59. gcd=exgcd(a,b,x,y),b=abs(b/gcd);
  60. x=(x*(c/gcd)%b+b)%b;
  61. ans+=M*x;
  62. M*=brr[i]/__gcd(brr[i],M);
  63. ans=(ans%M+M)%M;
  64. }
  65. return ans;
  66. }
  67. }crt;
  68. ll C(ll a,ll b,int ty) {
  69. if(ty==0)
  70. return comb[0].solve(a,b);
  71. else {
  72. int i,j;
  73. for(i=1;i<=4;++i) {
  74. crt.arr[i]=comb[i].solve(a,b);
  75. crt.brr[i]=array[i];
  76. }
  77. }
  78. return crt.Excrt();
  79. }
  80. int main() {
  81. int i,j,k,flag;
  82. // setIO("input");
  83. ll n,m,mod;
  84. scanf("%lld%lld%d%lld",&n,&m,&k,&mod),flag=(mod==1019663265);
  85. if(!flag) {
  86. comb[0].init(mod);
  87. }
  88. else {
  89. for(i=1;i<=4;++i)
  90. comb[i].init(array[i]);
  91. }
  92. for(i=1;i<=k;++i)
  93. scanf("%lld%lld",&arr[i].x,&arr[i].y);
  94. arr[++k].x=n,arr[k].y=m;
  95. sort(arr+1,arr+1+k,cmp);
  96. for(i=1;i<=k;++i) {
  97. F[i]=C(arr[i].x+arr[i].y,arr[i].y,flag);
  98. for(j=1;j<i;++j) {
  99. if(arr[j].y<=arr[i].y)
  100. 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;
  101. }
  102. }
  103. printf("%lld\n",F[k]);
  104. return 0;
  105. }

  

BZOJ 3782: 上学路 Lucas+ExCRT+容斥+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]

    3782: 上学路线 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 192  Solved: 75[Submit][Status][Discuss] ...

  3. bzoj3782上学路线(Lucas+CRT+容斥DP+组合计数)

    传送门:https://www.lydsy.com/JudgeOnline/problem.php?id=3782 有部分分的传送门:https://www.luogu.org/problemnew/ ...

  4. 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 ...

  5. $bzoj2560$ 串珠子 容斥+$dp$

    正解:容斥+$dp$ 解题报告: 传送门$QwQ$ $umm$虽然题目蛮简练的了但还是有点难理解,,,我再抽象一点儿,就说有$n$个点,点$i$和点$j$之间有$a_{i,j}$条无向边可以连,问有多 ...

  6. [CF1086E]Beautiful Matrix(容斥+DP+树状数组)

    给一个n*n的矩阵,保证:(1)每行都是一个排列 (2)每行每个位置和上一行对应位置不同.求这个矩阵在所有合法矩阵中字典序排第几.考虑类似数位DP的做法,枚举第几行开始不卡限制,那么显然之前的行都和题 ...

  7. 【BZOJ3622】已经没有什么好害怕的了 容斥+DP

    [BZOJ3622]已经没有什么好害怕的了 Description Input Output Sample Input 4 2 5 35 15 45 40 20 10 30 Sample Output ...

  8. BZOJ.4767.两双手(组合 容斥 DP)

    题目链接 \(Description\) 棋盘上\((0,0)\)处有一个棋子.棋子只有两种走法,分别对应向量\((A_x,A_y),(B_x,B_y)\).同时棋盘上有\(n\)个障碍点\((x_i ...

  9. BZOJ 2005 [Noi2010]能量采集 (数学+容斥 或 莫比乌斯反演)

    2005: [Noi2010]能量采集 Time Limit: 10 Sec  Memory Limit: 552 MBSubmit: 4493  Solved: 2695[Submit][Statu ...

随机推荐

  1. markdown中使用缩进

    在markdown中直接敲空格是不生效的. 使用html标签来实现 一个空格大小的表示:  两个空格的大小表示:  不换行空格:  别忘记分号 参考了大神的文章: markdown空格缩进以及HTML ...

  2. 并不对劲的复健训练-p5212 SubString

    题目大意 有一个串\(s\),一开始只知道它的一个前缀.有\(q\)(\(q\leq 10^4\))个操作,操作有两种:1.给一个字符串,表示\(s\)(\(s\)总长\(\leq 6\times 1 ...

  3. EasyUI_前台js_分页

    1.html: <table id="DataTb" title="客户信息" class="easyui-datagrid" sty ...

  4. 使用EF Core 连接远程oracle 不需要安装oracle客户端方法

    连接字符串: Data Source=(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=IP地址(PORT=1521))(CONNECT_DATA=(SERVICE_ ...

  5. luogu题解P2502[HAOI2006]旅行--最小生成树变式

    题目链接 https://www.luogu.org/problemnew/show/P2502 分析 一个很\(naive\)的做法是从\(s\)到\(t\)双向BFS这当然会TLE 这时我就有个想 ...

  6. 始终让footer在底部

    1.footer保持在页面底部 需求: 我们希望footer能在窗口最底端,但是由于页面内容太少,无法将内容区域撑开,从而在 footer 下面会留下一大块空白 第一种方法:采用 flexbox布局模 ...

  7. sql server 2012使用新特性offset和fetch next完成分页操作

    1 select * from HumanResources.Department order by DepartmentID offset rows fetch next rows only; of ...

  8. 第二十四篇 jQuery 学习6 删除元素

    jQuery 学习6 删除元素   上节课我们做了添加元素,模拟的是楼主发的文章,路人评论,那么同学们这节课学了删除之后,去之前的代码上添加一个删除,模拟一个楼主删除路人的评论. jQuery的删除方 ...

  9. JavaMaven【六、生命周期】

    Maven有三个独立的生命周期,每个生命周期都不会出发别的生命周期的操作 若直接执行生命周期后面的操作,maven会默认执行前面的操作 如项目创建好后,直接执行mvn install,会默认依次执行c ...

  10. JavaJDBC【四、存储过程的使用】

    Mysql还没学到存储过程,不过语法比较简单 此处不深究数据库中的存储过程怎么创建,后面在mysql的学习笔记里再做整理 今天只整理java中如何调用存储过程 语句 CallableStatement ...