【bzoj3782】上学路线 dp+容斥原理+Lucas定理+中国剩余定理
题目描述
输入
输出
样例输入
3 4 3 1019663265
3 0
1 1
2 2
样例输出
8
提示
p=1000003 或 p=1019663265
题解
dp+Lucas定理+中国剩余定理
设$f[i]$表示从$(0,0)$走到第i个坏点(终点算作第T+1个坏点),中途不经过其它坏点的方案数。
那么直接求$f[i]$比较困难,考虑单步容斥,用总方案数-经过坏点的方案数推出$f[i]$。
从$(0,0)$走到$(n,m)$的总方案数为$C_{n+m}^n$,可以看做总共n+m步,其中n步是x方向。
而经过坏点的方案数,枚举其经过的第一个坏点,那么它的贡献为|从$(0,0)$走到该点,中途不经过其它坏点的方案数|*|从这个坏点走到当前点的方案数|。
第一个即为坏点的$f$值,第二个用组合数求法求出。
最后的答案就是$f[T+1]$。
然而本题较为恶心之处在于模数,当p=1000003时可以直接使用Lucas定理,而当p=1019663265时p不为质数,将其分解质因数为3*5*6793*10007,使用Lucas定理分别求出组合数在模这些质因子意义下的值,再使用中国剩余定理CRT合并,才能得到组合数模1019663265的值。
细节还是有点多,代码已经差不多优化到极限了,凑合着看吧。。
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
const ll mod[] = {1000003 , 3 , 5 , 6793 , 10007} , temp = 1019663265;
struct data
{
ll x , y;
bool operator<(const data a)const {return x == a.x ? y < a.y : x < a.x;}
}a[210];
ll f[210] , fac[5][1000010] , d[5];
bool flag;
ll pow(ll x , ll y , ll p)
{
ll ans = 1;
while(y)
{
if(y & 1) ans = ans * x % p;
x = x * x % p , y >>= 1;
}
return ans;
}
ll choose(ll n , ll m , ll p)
{
if(n < m) return 0;
if(n < mod[p] && m < mod[p]) return fac[p][n] * pow(fac[p][m] , mod[p] - 2 , mod[p]) % mod[p] * pow(fac[p][n - m] , mod[p] - 2 , mod[p]) % mod[p];
return choose(n / mod[p] , m / mod[p] , p) * choose(n % mod[p] , m % mod[p] , p) % mod[p];
}
ll C(ll n , ll m)
{
if(!flag) return choose(n , m , 0);
int i;
ll ans = 0;
for(i = 1 ; i < 5 ; i ++ ) d[i] = choose(n , m , i);
for(i = 1 ; i < 5 ; i ++ ) ans = (ans + temp / mod[i] * pow(temp / mod[i] , mod[i] - 2 , mod[i]) % temp * d[i] % temp) % temp;
return ans;
}
int main()
{
ll n , m;
int p , T , i , j;
scanf("%lld%lld%d%d" , &n , &m , &T , &p) , flag = (p != 1000003);
for(i = 0 ; i < 5 ; i ++ )
for(fac[i][0] = j = 1 ; j < mod[i] ; j ++ )
fac[i][j] = fac[i][j - 1] * j % mod[i];
for(i = 1 ; i <= T ; i ++ ) scanf("%lld%lld" , &a[i].x , &a[i].y);
a[++T].x = n , a[T].y = m;
sort(a + 1 , a + T + 1);
for(i = 1 ; i <= T ; i ++ )
{
f[i] = C(a[i].x + a[i].y , a[i].x);
for(j = 1 ; j < i ; j ++ )
if(a[j].y <= a[i].y)
f[i] = (f[i] - f[j] * C(a[i].y - a[j].y + a[i].x - a[j].x , a[i].y - a[j].y) % p + p) % p;
}
printf("%lld\n" , f[T]);
return 0;
}
【bzoj3782】上学路线 dp+容斥原理+Lucas定理+中国剩余定理的更多相关文章
- 卢卡斯定理&&中国剩余定理
卢卡斯定理(模数较小,且是质数) 式子C(m,n)=C(m/p,n/p)*C(m%p,n%p)%p 至于证明(我也不会QAQ,只要记住公式也该就好了). 同时卢卡斯定理一般用于组合数取模上 1.首先当 ...
- BZOJ 3782 上学路线 ——动态规划 Lucas定理 中国剩余定理
我们枚举第一个经过的坏点,然后DP即可. 状态转移方程不是难点,难点在于组合数的处理. 将狼踩尽的博客中有很详细的证明过程,但是我只记住了结论 $n=a_1 * p^k+a_2*p^k-1...$ $ ...
- 【bzoj1951】[Sdoi2010]古代猪文 费马小定理+Lucas定理+中国剩余定理
题目描述 求 $g^{\sum\limits_{k|n}C_{n}^{\frac nk}}\mod 999911659$ 输入 有且仅有一行:两个数N.G,用一个空格分开. 输出 有且仅有一行:一个 ...
- Ceizenpok’s formula Gym - 100633J 扩展Lucas定理 + 中国剩余定理
http://codeforces.com/gym/100633/problem/J 其实这个解法不难学的,不需要太多的数学.但是证明的话,我可能给不了严格的证明.可以看看这篇文章 http://ww ...
- hdu 5446 Unknown Treasure Lucas定理+中国剩余定理
Unknown Treasure Time Limit: 1500/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Other ...
- 【题解】P2480 [SDOI2010]古代猪文 - 卢卡斯定理 - 中国剩余定理
P2480 [SDOI2010]古代猪文 声明:本博客所有题解都参照了网络资料或其他博客,仅为博主想加深理解而写,如有疑问欢迎与博主讨论✧。٩(ˊᗜˋ)و✧*。 题目描述 猪王国的文明源远流长,博大精 ...
- Codeforces Round #460 (Div. 2).E 费马小定理+中国剩余定理
E. Congruence Equation time limit per test 3 seconds memory limit per test 256 megabytes input stand ...
- 洛谷P2480 [SDOI2010]古代猪文(费马小定理,卢卡斯定理,中国剩余定理,线性筛)
洛谷题目传送门 蒟蒻惊叹于一道小小的数论题竟能涉及这么多知识点!不过,掌握了这些知识点,拿下这道题也并非难事. 题意一行就能写下来: 给定\(N,G\),求\(G^{\sum \limits _{d| ...
- RSA遇上中国剩余定理
1.Introduction 最近读论文刚好用到了这个,之前只是有耳闻,没有仔细研究过,这里就好好捋一下,会逐步完善 不过貌似CRT(中国剩余定理)的实现更容易被攻击 2. RSA: Overview ...
随机推荐
- java入门第一章——java开发入门
习题解答 一.填空题 (p2)1.java的三个技术平台分别是(java SE.java EE.java ME)(标准.企业.小型) (p3)2.java程序的运行环境简称为(JRE)(开发环境-JD ...
- UVALive 3983 Robotruck (单调队列,dp)
如果状态定义为序号和重量的话,决策就是下一个垃圾捡或者不减,但是状态数太多了. 如果只定义序号作为状态的话,决策就变成从前面的某个j一直捡到i才送回垃圾. 这就变成了一个区间选最小值的问题,用单调队列 ...
- UVA 1616 Caravan Robbers 商队抢劫者(二分)
x越大越难满足条件,二分,每次贪心的选区间判断是否合法.此题精度要求很高需要用long double,结果要输出分数,那么就枚举一下分母,然后求出分子,在判断一下和原来的数的误差. #include& ...
- 2018.3.26 Linux下学习命令
Linux下的终端文件颜色说明 ---color[=WHEN] 用色彩辨别文件类型 WHEN 可以是'never'.'always'或'auto'其中之一 白色:表示普通文件 蓝色:表示目录 绿色:表 ...
- Dojo的declare接口
declare(classname,[],{}) declare的第一个参数是可选的,代表类的名称 declare的第二个参数代表类的继承关系,比如继承哪一个父类,可以看到:第二个参数是一个数组,所以 ...
- C#访问数组元素
在C#中,使用索引来访问数组元素.索引必须是一个整型值. 在数组中,每一个维度的索引从0开始. 一.访问一维数组元素 int[] array = {1,2,3,4,5,6,7,8,9,10}; // ...
- deque 用法
引用博客:https://blog.csdn.net/zyq522376829/article/details/46801973 下面是那位大佬写的的笔记整理~~~~ deque - 双向队列 1.构 ...
- STL之stack操作
c++ stl栈stack介绍 C++ Stack(堆栈) 是一个容器类的改编,为程序员提供了堆栈的全部功能,——也就是说实现了一个先进后出(FILO)的数据结构. c++ stl栈stack的头文件 ...
- Mysql数据库插入中文出现乱码相关
查看数据库编码的命令:show variables like "character%"; mysql> show variables like "character ...
- Spring源码剖析依赖注入实现
Spring源码剖析——依赖注入实现原理 2016年08月06日 09:35:00 阅读数:31760 标签: spring源码bean依赖注入 更多 个人分类: Java 版权声明:本文为博主原 ...