怎样求大组合数(取模)(ACM算法)比如我要求c(m1+m2,n),(0 < n

来源:学生作业帮助网 编辑:作业帮 时间:2024/05/06 01:49:34
怎样求大组合数(取模)(ACM算法)比如我要求c(m1+m2,n),(0 < n

怎样求大组合数(取模)(ACM算法)比如我要求c(m1+m2,n),(0 < n
怎样求大组合数(取模)(ACM算法)
比如我要求c(m1+m2,n),(0 < n

怎样求大组合数(取模)(ACM算法)比如我要求c(m1+m2,n),(0 < n
这种题目然做过的,
意思比较简单,就由 m 个共 0 和 n 个 1 组成一个串,但从左到右要1出现的次数不少于0出现的次数.
由大牛的算法:结果就是 C(m+n,n) - C(m+n,m-1) 再取模,我们可以对式子化简一下就是:
(n+m)!*
(n-m+1) / ((m)!* (n+1)!)
再取模,但由于组合数很大,直接用大数乘除就会超时了,看了别人的报告才知道原来可以用素数化简快速求模的,n!= 2^p[i] *
3^p[i] * 5^p[i]*.再求模就可以很快了~(^ = ^)~.
#include
#include
#include
using namespace std;
#define M 2000005
#define mm 20100501
bool sig[M];
int prime[150000],p[150000],len; // prime 记录素数,p 记录素数的幂 len 记录长度
void getprime() // 筛法找素数
{
int i,j,k=0;
prime[k++] = 2;
for(i=3; in>>m;
len = 0;
memset(p,0,sizeof(p));
mid = n-m+1; //先前要把 n-m+1 的因子加进 P 中去才能使 (m+n)!/ ((m)!*(n+1)!) 整除
for(i=0; mid>1; i++)
{
if( mid%prime[i] == 0)
{
while(mid%prime[i]==0)
{
p[i] += 1;
mid /= prime[i];
}
}
}
get(m+n,1);
get(m,0);
get(n+1,0);
ans = cal();
printf("%I64d\n",ans);
}
return 0;
}
可以用素数分解法,
先求出上面和下面的素数表示,然后约分后,再用求幂公式

这种题目然做过的,
意思比较简单,就由 m 个共 0 和 n 个 1 组成一个串,但从左到右要1出现的次数不少于0出现的次数。
由大牛的算法: 结果就是 C(m+n, n) - C(m+n, m-1) 再取模,我们可以对式子化简一下就是:
(n+m)!*
(n-m+1) / ((m)!* (n+1)!)
再取模,但由于组合数很大,直接用大数乘除就会超时...

全部展开

这种题目然做过的,
意思比较简单,就由 m 个共 0 和 n 个 1 组成一个串,但从左到右要1出现的次数不少于0出现的次数。
由大牛的算法: 结果就是 C(m+n, n) - C(m+n, m-1) 再取模,我们可以对式子化简一下就是:
(n+m)!*
(n-m+1) / ((m)!* (n+1)!)
再取模,但由于组合数很大,直接用大数乘除就会超时了,看了别人的报告才知道原来可以用素数化简快速求模的, n! = 2^p[i] *
3^p[i] * 5^p[i]*...... 再求模就可以很快了~(^ = ^)~。。。

#include
#include
#include
using namespace std;
#define M 2000005
#define mm 20100501
bool sig[M];
int prime[150000], p[150000], len; // prime 记录素数, p 记录素数的幂 len 记录长度
void getprime() // 筛法找素数
{
int i,j,k=0;
prime[k++] = 2;
for(i=3; i<=M; i+=2)
{
if( !sig[i] )
{
prime[k++] = i;
for(j=i; j<=M; j+=i)
sig[j] = 1;
}
}
}
void get(int k, int s) // K! 的素数分解, S为指数的加减(分母,分子)
{
int i, mid;
for(i=0; prime[i]<=k && prime[i]; i++)
{
mid = k;
while(mid)
{
if(s)
p[i] += mid/prime[i];
else
p[i] -= mid/prime[i];
mid /= prime[i];
}
}
if(len < i)
len = i;
}
__int64 cal() // 计算结果 (prime[i...]^p[i...]) % mm
{
__int64 i,ans = 1;
for(i=0; i<=len; i++)
{
if( p[i] )
{
__int64 t = prime[i], b = p[i], ret = 1;
while(b) //计算 (t^b) % mm
{
if(b%2) ret *= t %mm;
t = t*t%mm;
b /= 2;
}
ans = ( ans*ret ) % mm;
}
}
return ans;
}
int main()
{
int t,m,n,i,mid;
__int64 ans;
getprime();
cin>>t;
while(t--)
{
cin>>n>>m;
len = 0;
memset(p, 0, sizeof(p));
mid = n-m+1; //先前要把 n-m+1 的因子加进 P 中去才能使 (m+n)! / ((m)!*(n+1)!) 整除
for(i=0; mid>1; i++)
{
if( mid%prime[i] == 0)
{
while(mid%prime[i]==0)
{
p[i] += 1;
mid /= prime[i];
}
}
}
get(m+n, 1);
get(m, 0);
get(n+1, 0);
ans = cal();
printf("%I64d\n", ans);
}
return 0;
}
可以用素数分解法,
先求出上面和下面的素数表示,然后约分后,再用求幂公式

收起

怎样求大组合数(取模)(ACM算法)比如我要求c(m1+m2,n),(0 < n 求北大ACM 3909答案(写明算法) 求一个数的最大公约数和最小公倍数的算法是怎样的?还有对一组数的全排列和全组合算法是怎样的?韵儿榕儿 - 魔法学徒 一级 能不能举例详细说明下欧几里德算法 是怎么样的? 一道ACM编程题 求算法思路.给出一些无序的数比如5 3 4 2 1每次可以交换其中任意2个数现在求最少的交换次数 使序列变得从小到大有序怎么求最小的交换次数呢?说下思路就行了希望算法够快 求组合数:求n个数(1.n)中k个数的组合. 杭电acm 2035 题的算法是怎样的,杭电acm 2035 题的算法是怎样的,我要算法分析,不要代码!Problem Description求A^B的最后三位数表示的整数.说明:A^B的含义是“A的B次方”Input输入数据包含多个测试实 如何计算M个元素中取N个数共能组合出几种不重复!的组合.(比如1221与1122算一个!) (1)等腰三角形的腰长为m,求底边x的取值范围?(2)底边三角形的边长的acm,求它的面积? 求教!输出和为100的连续数的算法是正整数!比如求和为1000的连续正整数,有个组合为:198、199、 200、201 、202 小时转换分钟数比如有48.78小时,转换成 小时加分钟数,是怎样的算法? 从10个不同的数中任意取2个数,求其和差积商.则这4个问题中属于组合的有 (不是编程,组合排列) 求ACM各大OJ的解题报告,最好是经过整理分类的,希望有大家提交的所有代码(估计不现实了.没后台.) 解m个自然数中取n个数的总和为a的组合数(a,m,n属于正整数)比如:m=100,n=20,a=1000,求其组合数是多少,不需要具体的组合. acm算法书籍求推荐 除了白书 还有什么详细讲解数据结构的? acm 输入一系列数计算和.1.23.4.5..直到文件结束.) 组合数性质二数等于n个元素中取m个数所构成的组合数加n个元素中取m-1个数所构成的组合数)书上说把n+1分为带a和不带a的两组,为什么要这样分?为什么就得出这个性质? 求枚举组合算法1-8 的所有6位组合123456124653135721.任意的都要组合,不能漏掉可能组合的任意一组...求完整算法... 数据结构排序算法中元素的平均移动次数如何求比如快速排序和归并排序(二路)算法的平均移动次数