博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
LCM性质 + 组合数 - HDU 5407 CRB and Candies
阅读量:6786 次
发布时间:2019-06-26

本文共 2519 字,大约阅读时间需要 8 分钟。

题目描述

给定一个数n,求LCM(C(n,0),C(n,1),C(n,2)...C(n,n))的值,(n<=1e6)。

解题思路

很有趣的一道数论题!

看了下网上别人的做法,什么Kummer定理我还真没听说过,仔细研究一下那个鬼定理真是涨姿势了!

然而这题我并不是用Kummer那货搞的(what?).

其实这题真的很简单(不要打我),为什么这样说呢?看了下面的解释你就知道我没骗你。

首先我们看一下这个式子:LCM(C(n,0),C(n,1),C(n,2)...C(n,n))

当时我的第一感觉是:晕,还是打个表吧!结果,打表程序后台打了四个半小时也没打完=.=(时间复杂度算错了)

做这题首先你得知道这个(基本常识):

求多个数的最小公倍数,有两种方法:

1)分解质因数法

先把这几个数分解质因数,再把它们一切公有的质因数和其中几个数公有的质因数以及每个数的独有的质因数全部连乘起来,所得的积就是它们的最小公倍数。

例如,求LCM[12,18,20,60]

因为12=(2)×[2]×[3],18=(2)×[3]×3,20=(2)×[2]×{5},60=(2)×[2]×[3]×{5}

其中四个数的公有的质因数为2(小括号中的数),

三个数的公有的质因数为2与3[中括号中的数],

两个数的公有的质因数为5{大括号中的数},

每个数独有的质因数为3。

所以,[12,18,20,60]=2×2×3×3×5=180。

2)公式法

由于两个数的乘积等于这两个数的最大公约数与最小公倍数的积

即(a,b)×[a,b]=a×b。

所以,求两个数的最小公倍数,就可以先求出它们的最大公约数,然后用上述公式求出它们的最小公倍数

例如,求[18,20]

即得[18,20]=18×20÷(18,20)=18×20÷2=180。

求几个自然数的最小公倍数,可以先求出其中两个数的最小公倍数,

再求这个最小公倍数与第三个数的最小公倍数,依次求下去,直到最后一个为止。

最后所得的那个最小公倍数,就是所求的几个数的最小公倍数。

知道这个后,做这题选择哪种方法呢?

如果选择第二种方法,恭喜你,你绝壁和我一样想到打表滚粗!

既然第二种方法不行,肯定只能是第一种方法了。

那么要怎么做呢?

首先我们来看,对于组合数C(n,m),可以有如下变换:

C(n,m)=n!/[(n-m)!*m!]=n*(n-1)*(n-2)*....(m+1) / (n-m)! 

这一步应该没问题吧!

也就是:C(n,m)=n!/[(n-m)!*m!]=n*(n-1)*(n-2)*....(m+1) / (n-m)!  = n*(n-1)*(n-2)*....(m+1)/1/2/3/4/5/..../(n-m)

我们把前后结合一下,边乘边除:

对于第k步,就相当于*(n+1-k)且/k,k={1,2,...n-m}.

我们以n=8为例:

C(8,0)=1

C(8,1)=8*7*6*5*4*3*2 /7/6/5/4/3/2/1

C(8,2)=8*7*6*5*4*3 /6/5/4/3/2/1

C(8,3)=8*7*6*5*4 /5/4/3/2/1

C(8,4)=8*7*6*5 /4/3/2/1

C(8,5)=8*7*6 /3/2/1

C(8,6)=8*7 /2/1

C(8,7)=8 /1

C(8,8)=1

结合求n个数的LCM的方法,我们将问题转换成:

找i个数共有的质数,然后相乘就可,i={1,2,..n}。

好了,你可能会说:*$#@*@,找i个数共有的质数难道不超时,而且你的代码里连一个0~n的for循环都没有,你在逗我?

不急,看下面:

首先我们明确一点,C(n,k)的最大质因数是不会大于n的。

那么对于一个质数p来说,他对"n个数的LCM"的贡献在哪?

是不是就是p^1,p^2,p^3...中的一些?

哪些呢?

前面求组合数中,我们把C(n,m)分成了分子和分母来看。

如果p^x能够整除(n-1+k),那么他有可能是满足的,但是还不够,还要看是不是会被分母抵消掉。

只有p^x满足(n-1+k)%(p^x)==0且满足k%(p^x)!=0,这个p^x才是满足的,也就是对答案才有贡献,此时ans需要乘以p。

最后一步,约约分可能会更方便:把分子分母合一下,变成了:(n-1)%(p^x)!=0,表示(n-1+k)%(p^x)==0和k%(p^x)!=0不是同时出现的,此时才满足。

OK,推导完毕。

最终方法就是:

先筛出1e6以内的所有素数p,然后判断(n-1)%(p^x)是否!=0,是的话,ans*=p。

 

时间复杂度

O(p_num*sqrt(n))

代码

/** this code is made by crazyacking* Verdict: Accepted* Submission Date: 2015-08-21-15.17* Time: 0MS* Memory: 137KB*/#include 
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define mod 1000000007#define LL long long#define ULL unsigned long longusing namespace std;const int NN=1000010;bool v[NN];int p[NN],num;void makePrime(){ int i,j; num=-1; for(i=2; i

转载于:https://www.cnblogs.com/crazyacking/p/4748294.html

你可能感兴趣的文章
JPush极光推送Java服务器端实例
查看>>
trie 转载(来源于http://www.cnblogs.com/njuzyc/archive/2012/01/25/2329332.html)
查看>>
Office提示由于本机的限制该操作已被取消怎么办
查看>>
Google Earth网页版初探
查看>>
Mysql数据库连接池知识分享
查看>>
SpringMVC 拦截请求,判断会话是否超时
查看>>
网站前端_KindEditor.基础入门.0001.KindEditor_3.4.2快速入门?
查看>>
android拍照并通过Http发送到Java后台
查看>>
ubuntu安装nginx-1.8.0.tar.gz
查看>>
魔兽争霸3地图(WarIII Maps):妖皇传说
查看>>
grub2正确配置——硬盘安装ubuntu 9.10之后不能启动xp解决方法
查看>>
PHP isset()与empty()的使用区别详解
查看>>
mysql 修改数据库的时区
查看>>
MyBatis 通过包含的jdbcType类型
查看>>
Web应用中的中文问题
查看>>
with as 中绑定变量的使用
查看>>
时间:2014年4月8日17:01:10 GD完成验证码
查看>>
mysql主从同步
查看>>
微信机器人高级版常见问题汇总
查看>>
容器技术|Docker三剑客之docker-machine
查看>>