【算法】卢卡斯定理

【问题描述】

OI大师抖儿在夺得银牌之后,顺利保送pku。这一天,抖儿问长者:“虽然我已经保送了,但是我还要参加学考。马上就要考政治了,请问应该怎样学习哲学,通过政治考试?”
长者回答:“你啊,Too
Young Too Simple,Sometimes Naive!哲学这种东西,不是说想懂就能懂的,需要静心撕烤。你去后面的森林里好好想想。”

长者的后院有一片哲♂学森林。由于一些奥妙重重的原因,这片森林构成了一个n*m的矩形,其中每个点就代表了一棵树。此外,由于辣鸡出题人KJDH从中捣鬼,有些树被连根拔起(也就是消失了)。抖儿每天都要到树下撕烤,因此他想要在每一行选择一棵树。但是他非常讨厌走回头路,因此第i行选择的树必须比第i-1行的靠右。现在抖儿想知道,总共有多少种选择的方案。

【输入格式】

第一行三个整数n,m,p,分别表示森林的长、宽,以及消失的树的数目。

接下来p行每行两个整数,表示第ai行第bi列的树消失了。

p<=2000 n,m<=10^9

【输出格式】

一行一个整数,表示方案数。由于答案可能很大,请对1000003取模。

【题解】

C(n,m)%p=C(n%p,M%p)*C(n/p,m/p)%p

显然向下x个单位,向右y个方案是C(x-1,y-1)

f[i]只到第i个点的方案数

f[i]=C(x[i]-1,y[i]-1)-sigma(f[j]*C(x[i]-x[j]-1,y[i]-y[j]-1))(y[i]>=y[j]&&x[i]>=x[j]&&i>j)

#include<stdio.h>
#include<stdlib.h>
#include<iostream>
#include<string>
#include<string.h>
#include<algorithm>
#include<math.h>
#include<queue>
#include<map>
#include<vector>
#include<set>
#define il inline
#define re register
#define mod 1000003
using namespace std;
typedef long long ll;
const int N=2016;
int n,a[1100000],r[1100000],m,p,f[N];
struct data{int x,y;} t[N];
il bool cmp(data a,data b){
    return a.x<b.x;
}
il int C(int n,int m){
    if(n<m) return 0;
    if(n<mod) return 1ll*a[n]*r[m]*r[n-m]%mod;
    return 1ll*C(n/mod,m/mod)*C(n%mod,m%mod)%mod;
}
int main(){
    freopen("zhexue.in","r",stdin);
    freopen("zhexue.out","w",stdout);
    a[0]=1;r[1]=1;r[0]=1;
    for(int i=1;i<mod;i++) a[i]=1ll*a[i-1]*i%mod;
    for(int i=2;i<mod;i++) r[i]=1ll*r[mod%i]*(mod-mod/i)%mod;
    for(int i=1;i<mod;i++) r[i]=1ll*r[i]*r[i-1]%mod;
    scanf("%d%d%d",&n,&m,&p);
    for(int i=1;i<=p;i++)
        scanf("%d%d",&t[i].x,&t[i].y);
    t[++p].x=n+1;t[p].y=m+1;
    sort(t+1,t+p+1,cmp);
    for(int i=1;i<=p;i++){
        f[i]=C(t[i].y-1,t[i].x-1);
        //cout<<f[i]<<endl;
        for(int j=1;j<i;j++)
            if(t[j].x<t[i].x&&t[j].y<t[i].y){
                f[i]=((f[i]-1ll*f[j]*C(t[i].y-t[j].y-1,t[i].x-t[j].x-1)%mod)%mod+mod)%mod;
            }
    }
    cout<<f[p];
    return 0;
}
时间: 2024-08-07 08:38:40

【算法】卢卡斯定理的相关文章

卢卡斯定理的模板以及应用

定义: Lucas定理是用来求 C(n,m) MOD p,p为素数的值.Lucas定理:我们令n=sp+q,m=tp+r.(q,r≤p) 那么:(在编程时你只要继续对 调用 Lucas 定理即可.代码可以递归的去完成这个过程,其中递归终点为 t=0 :时间复杂度 O(logp(n)?p):) 主要解决当 n,m 比较大的时候,而 p 比较小的时候 <1e6 ,那么我们就可以借助 卢卡斯定理来解决这个问题: 模板: #include <iostream> #include <cstd

cf451E Devu and Flowers 卢卡斯定理+容斥定理

题目:http://codeforces.com/problemset/problem/451/E 题意:有n个盒子(n<=20),每个盒子中有10^12个小球,现从每个盒子中取出若干球(可为0),求共取出s个小球(s<=10^14)的方案数. 组合数学问题,求C(n,m).但n,m过大时,可用卢卡斯定理. 卢卡斯定理:C(n,m) %p = C(n/p,m/p) * C(n%p,m%p) 从n个盒子中取出s个球的方案数,相当于插板,即 C(s+n-1,n-1).注意这是没有限制条件的情况.

Xiao Ming&#39;s Hope 卢卡斯定理的推广。

Xiao Ming's Hope 题目抽象:求C(n,0),C(n,1),……,C(n,n)中奇数的个数. 思路:考察C(n,m)%2. 由卢卡斯定理    C(A,B)=C(a[n-1],b[n-1])*C(a[n-2],b[n-2])* ……*C(a[0],b[0])  ,其中a[i]为A的p进制位 要使C(n,m)%2==1,  那么对于n上的1的位,m上对应的位可以为0,1,(c(1,0)=c(1,1)=1). 对于n上为0的位,m上对应的位必须为0.(c(0,0)=1,c(0,1)=0

洛谷——P3807 【模板】卢卡斯定理

P3807 [模板]卢卡斯定理 题目背景 这是一道模板题. 题目描述 给定n,m,p(1\le n,m,p\le 10^51≤n,m,p≤10?5??) 求 C_{n+m}^{m}\ mod\ pC?n+m?m?? mod p C表示组合数. 一个测试点内包含多组数据. 输入输出格式 输入格式: 第一行一个整数T(T\le 10T≤10),表示数据组数 第二行开始共T行,每行三个数n m p,意义如上 输出格式: 共T行,每行一个整数表示答案. 输入输出样例 输入样例#1: 2 1 2 5 2

卢卡斯定理

卢卡斯定理:解决一类组合数取模问题 A.B是非负整数,p是质数.AB写成p进制:A=a[n]a[n-1]...a[0],B=b[n]b[n-1]...b[0]. 则组合数C(A,B)与C(a[n],b[n])*C(a[n-1],b[n-1])*...*C(a[0],b[0])  modp同余 即:Lucas(n,m,p)=c(n%p,m%p)*Lucas(n/p,m/p,p) 这个是单独处理n!的情况,当然C(n,m)就是n!/(m!*(n-m)!),每一个阶乘都用上面的方法处理的话,就是Luc

【BZOJ 4403】 4403: 序列统计 (卢卡斯定理)

4403: 序列统计 Time Limit: 3 Sec  Memory Limit: 128 MBSubmit: 653  Solved: 320 Description 给定三个正整数N.L和R,统计长度在1到N之间,元素大小都在L到R之间的单调不降序列的数量.输出答案对10^6+3取模的结果. Input 输入第一行包含一个整数T,表示数据组数.第2到第T+1行每行包含三个整数N.L和R,N.L和R的意义如题所述. Output 输出包含T行,每行有一个数字,表示你所求出的答案对106+3

【BZOJ 1272】 1272: [BeiJingWc2008]Gate Of Babylon (容斥原理+卢卡斯定理)

1272: [BeiJingWc2008]Gate Of Babylon Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 254  Solved: 120 Description Input Output Sample Input Sample Output 12 HINT Source [分析] T很小,跟以前的某一题很像啊,就是容斥. 枚举不符合的(超过限制的),2^t,然后就是算 n种无限多的东东中选m个. 经典的组合数题,$C_{n+m-1

【BZOJ 2982】 2982: combination (卢卡斯定理)

2982: combination Time Limit: 1 Sec  Memory Limit: 128 MBSubmit: 510  Solved: 316 Description LMZ有n个不同的基友,他每天晚上要选m个进行[河蟹],而且要求每天晚上的选择都不一样.那么LMZ能够持续多少个这样的夜晚呢?当然,LMZ的一年有10007天,所以他想知道答案mod 10007的值.(1<=m<=n<=200,000,000) Input   第一行一个整数t,表示有t组数据.(t&l

HDU 5794 A Simple Chess(卢卡斯定理 + 容斥原理)

传送门 A Simple Chess Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 667    Accepted Submission(s): 168 Problem Description There is a n×m board, a chess want to go to the position (n,m) from the

洛谷 P3807 【模板】卢卡斯定理

题目背景 这是一道模板题. 题目描述 给定n,m,p(1\le n,m,p\le 10^51≤n,m,p≤105) 求 C_{n+m}^{m}\ mod\ pCn+mm? mod p 保证P为prime C表示组合数. 一个测试点内包含多组数据. 输入输出格式 输入格式: 第一行一个整数T(T\le 10T≤10),表示数据组数 第二行开始共T行,每行三个数n m p,意义如上 输出格式: 共T行,每行一个整数表示答案. 输入输出样例 输入样例#1: 复制 2 1 2 5 2 1 5 输出样例#