【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 ...
随机推荐
- cesium模型加载-加载fbx格式模型
整体思路: fbx格式→dae格式→gltf格式→cesium加载gltf格式模型 具体方法: 1. fbx格式→dae格式 工具:3dsMax, 3dsMax插件:OpenCOLLADA, 下载地址 ...
- UVA 11468 Substring (AC自动机)
用把失配边也加到正常边以后AC自动机,状态是长度递减的DAG,每次选一个不会匹配字符的转移. dp[u][L]表示当前在tire树上u结点长度还剩L时候不匹配的概率,根据全概率公式跑记忆化搜索. #i ...
- UVA11090 Going in Cycle (二分+判负环)
二分法+spfa判负环.如果存在一个环sum(wi)<k*x,i=0,1,2...,k,那么每条边减去x以后会形成负环.因此可用spfa来判负环. 一般spfa判负环dfs最快,用stack次之 ...
- TextView中使用Linkify添加超链接
首先,在TextView所属xml配置文件中,直接添加android:autoLink特性即可,它支持一个或多个(用分割线)自定义的值:none.web.email.phone或all. 另外, ...
- Python2 和Python3 的区别
print Python 2中的print语句被Python 3中的print()函数取代,这意味着在Python 3中必须用括号将需要输出的对象括起来. 在Python 2中使用额外的括号也是可以的 ...
- vector 下标操作
比如:vector<int> ivec(3).. 当采用下标操作ivec[10]的时候,该操作是未定义的,在自己的机器上输出的值是零.建议使用迭代器进行操作.
- Java(面试题):字符串截取
在Java中,字符串“abcd”与字符串“ab你好”的长度是一样,都是四个字符. 但对应的字节数不同,一个汉字占两个字节. 定义一个方法,按照指定的字节数来取子串. 如:对于“ab你好”,如果取三个字 ...
- Nginx超时配置
Nginx超时配置 1.client_header_timeout 语法client_header_timeout time 默认值60s 上下文http server 说明 指定等待client发送 ...
- Docker 守护进程的配置和操作 & 远程访问
守护进程的配置和操作 1.查看守护进程 linux命令: ps -ef | gerp docker sudo status docker 2.开启关闭重启守护进程 sudo service docke ...
- C#基础-字符串
字符串比较,strA.CompareTo(strB) A大于B 正数 A小于B 负数 A等于B 0 string strA = "ab"; string strB = " ...