ZOJ 3557 How Many Sets II lucas 定理

插空法 大组合数取余

#include <cstdio>
#include <cstring>
using namespace std;
typedef long long LL;

//求整数x和y,使得ax+by=d, 且|x|+|y|最小。其中d=gcd(a,b)
void gcd(LL a, LL b, LL& d, LL& x, LL& y)
{
	if(!b)
	{
		d = a;
		x = 1;
		y = 0;
	}
	else
	{
		gcd(b, a%b, d, y, x);
		y -= x * (a/b);
	}
}
//计算模n下a的逆。如果不存在逆, 返回-1
LL inv(LL a, LL n)
{
	LL d, x, y;
	gcd(a, n, d, x, y);
	return d == 1 ? (x+n)%n : -1;
}
LL cm(LL n, LL m, LL p)
{
	LL ans1 = 1, ans2 = 1;
	while(m)
	{
		ans1 = ans1*n%p;
		ans2 = ans2*m%p;
		n--;
		m--;
	}
	return ans1*inv(ans2, p)%p;
}
LL lucas(LL n, LL m, LL p)
{
	if(m == 0)
		return 1;
	return lucas(n/p, m/p, p)*cm(n%p, m%p, p)%p;
}
int main()
{
	LL n, m, p;
	while(scanf("%lld %lld %lld", &n, &m, &p) != EOF)
	{
		printf("%lld\n", lucas(n-2*m+1+m, m, p));
	}
	return 0;
}
时间: 2024-08-09 12:35:53

ZOJ 3557 How Many Sets II lucas 定理的相关文章

zoj 3557 How Many Sets II

How Many Sets II Time Limit: 2 Seconds      Memory Limit: 65536 KB Given a set S = {1, 2, ..., n}, number m and p, your job is to count how many set T satisfies the following condition: T is a subset of S |T| = m T does not contain continuous numbers

ZOJ 3557-How Many Sets II(Lucas定理+插板法求组合数)

题目地址:ZOJ 3557 题意:给一个集合,一共n个元素,从中选取m个元素,满足选出的元素中没有相邻的元素,一共有多少种选法(结果对p取模1 <= p <= 10^9) 思路:用插板法求出组合数.既然是从n个数中选择m个数,那么剩下的数为n-m,那么可以产生n-m+1个空,这道题就变成了把m个数插到这n-m+1个空中有多少种方法,即C(n-m+1,m)%p.然后就Lucas定理上去乱搞.因为这道题的p较大,所以不能预处理. #include <stdio.h> #include

ZOJ3557 How Many Sets II( Lucas定理)

转载请注明出处: http://www.cnblogs.com/fraud/          ——by fraud How Many Sets II Time Limit: 2 Seconds      Memory Limit: 65536 KB Given a set S = {1, 2, ..., n}, number m and p, your job is to count how many set T satisfies the following condition: T is

zoj——3557 How Many Sets II

How Many Sets II Time Limit: 2 Seconds      Memory Limit: 65536 KB Given a set S = {1, 2, ..., n}, number m and p, your job is to count how many set T satisfies the following condition: T is a subset of S |T| = m T does not contain continuous numbers

zoj 3557 lucas定理

Given a set S = {1, 2, -, n}, number m and p, your job is to count how many set T satisfies the following condition: T is a subset of S |T| = m T does not contain continuous numbers, that is to say x and x+1 can not both in T Input There are multiple

西电校赛网络赛J题 lucas定理计算组合数

西电校赛网络赛J题  lucas定理计算组合数 问题 J: 找规律II 时间限制: 1 Sec  内存限制: 128 MB 提交: 96  解决: 16 [提交][状态][讨论版] 题目描述 现有数阵如下: 1    2  3   4     5    6 1   3   6  10  15 1   4  10   20 1   5   15 1    6 1 求这个数阵的第n行m列是多少(行列标号从1开始) 结果对10007取模 输入 多组数据,每组数据一行,包含两个整数n,m(1<=n<=

HDU3944-DP?(帕斯卡公式+Lucas定理)

DP? Time Limit: 10000/3000 MS (Java/Others)    Memory Limit: 128000/128000 K (Java/Others) Total Submission(s): 1930    Accepted Submission(s): 640 Problem Description Figure 1 shows the Yang Hui Triangle. We number the row from top to bottom 0,1,2,-

BZOJ 4403 2982 Lucas定理模板

思路: Lucas定理的模板题.. 4403 //By SiriusRen #include <cstdio> using namespace std; const int mod=1000003; #define int long long int cases,N,L,R,fac[mod],inv[mod]; int C(int n,int m){ if(n<m)return 0; if(n<mod&&m<mod)return fac[n]*inv[n-m]

HDU 3037 Saving Beans (数论,Lucas定理)

题意:问用不超过 m 颗种子放到 n 棵树中,有多少种方法. 析:题意可以转化为 x1 + x2 + .. + xn = m,有多少种解,然后运用组合的知识就能得到答案就是 C(n+m, m). 然后就求这个值,直接求肯定不好求,所以我们可以运用Lucas定理,来分解这个组合数,也就是Lucas(n,m,p)=C(n%p,m%p)* Lucas(n/p,m/p,p). 然后再根据费马小定理就能做了. 代码如下: 第一种: #pragma comment(linker, "/STACK:10240