hdu 5407 CRB and Candies(组合数+最小公倍数+素数表+逆元)暨2015暑期多校赛第10场

题意:

输入n,求c(n,0)到c(n,n)的所有组合数的最小公倍数。

输入:

首行输入整数t,表示共有t组测试样例。

每组测试样例包含一个正整数n(1<=n<=1e6)。

输出:

输出结果(mod 1e9+7)。

感觉蛮变态的,从比赛开始我就是写的这道题,比赛结束还是没写出来……

期间找到了逆元,最小公倍数,组合数的各种公式,但是爆了一下午tle。

比赛结束,题解告诉我,公式秒杀法……

但是公式看不懂,幸好有群巨解说,所以有些听懂了,但还是需要继续思考才能弄懂。

题解:

设ans[i]表示i的所有组合数的最小公倍数。

设f[i]表示从1到i的正整数的最小公倍数。

然后获得从f[i]到ans[i]的公式——ans[i] = f[i+1]/i。                anss[i-1] = (f[i]*inv[i])%Mod;

然后获得求f[i]的公式——

  if(i == p^k) f[i] = f[i-1]*p;

  else f[i] = f[i-1];

接下来需要做的就是找到那些i == p^k了。

解题步骤:

1. 打素数表;

2. 由素数表寻找i == p^k;

3. f[1] = 1,打f[]数组表和ans[]数组表;

4. 输入数据;

5. 根据输入数据和ans[]表输出答案。

我认为还有其他方法,因为ac的程序的运行时间从15ms到900+ms都有。更多方法持续寻找中。

我的(根据题解的)代码——

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <cmath>
 4 #include <algorithm>
 5 using namespace std;
 6
 7 #define LL long long
 8 const int N = 1000010;
 9 const int Mod = 1000000007;
10
11 int n, t;
12 LL ans, mid;
13 LL inv[N];
14 LL anss[N];
15 bool su2[N];
16 int su[N], su1[N];
17 LL f[N];                                                    //f[i]表示1~i的最小公倍数
18
19
20 void table()
21 {
22     inv[1] = 1;
23     for(int i = 2; i < N; i++)                              //求i的逆元
24     {
25         inv[i] = inv[Mod%i]*(Mod-Mod/i) % Mod;
26     }
27
28     memset(su2, 1, sizeof(su2));
29     memset(su1, 0, sizeof(su1));
30     su2[0] = su2[1] = 0;                                    //求N以内的素数
31     su2[2] = 1;
32     for(int i = 3; i < N; i++) su2[i] = i%2 == 0 ? 0 : 1;
33     for(int i = 3; i <= sqrt(N*1.0); i++)
34     {
35         if(su2[i])
36         {
37             for(int j = i*i; j <= N; j += 2*i)
38             {
39                 su2[j] = 0;
40             }
41         }
42     }
43     int k = 0;
44     for(int i = 0; i < N; i++)                              //打N以内的素数表
45     {
46         if(su2[i] == 1) su[k++] = i;
47     }
48     for(int i = 0; i < k; i++)                              //寻找满足p^k的数,其中p为素数,k为正整数
49     {
50         LL mid = su[i];
51         while(mid < N)
52         {
53             su1[mid] = su[i];
54             mid *= su[i];
55         }
56     }
57     f[1] = 1;                                               //打N以内的1~i的最小公倍数表
58     for(int i = 2; i < N; i++)
59     {
60         if(su1[i]) f[i] = f[i-1]*su1[i];
61         else f[i] = f[i-1];
62         f[i] %= Mod;
63         anss[i-1] = (f[i]*inv[i])%Mod;                      //答案表
64     }
65 }
66
67 int main()
68 {
69     //freopen("test.in", "r", stdin);
70     //freopen("test.out", "r", stdout);
71     table();
72     scanf("%d", &t);
73     while(t--)
74     {
75         scanf("%d", &n);
76         printf("%I64d\n", anss[n]);
77     }
78     return 0;
79 }

时间: 2024-10-14 23:19:04

hdu 5407 CRB and Candies(组合数+最小公倍数+素数表+逆元)暨2015暑期多校赛第10场的相关文章

HDU 5407 CRB and Candies(LCM +最大素因子求逆元)

[题目链接]click here~~ [题目大意]求LCM(Cn0,Cn1,Cn2....Cnn)%MOD 的值 [思路]来图更直观: 这个究竟是怎样推出的,说实话.本人数学归纳大法没有推出来,幸得一个大神给定愿文具体证明,点击这里:click here~~ 代码: #include <bits/stdc++.h> using namespace std; const int N=1e6+10; const int MOD=1e9+7; typedef long long LL; LL p[N

Hdu 5407 CRB and Candies (找规律)

题目链接: Hdu 5407 CRB and Candies 题目描述: 给出一个数n,求lcm(C(n,0),C[n,1],C[n-2]......C[n][n-2],C[n][n-1],C[n][n])%(1e9+7)是多少? 解题思路: 刚开始的时候各种开脑洞,然后卡题卡的风生水起.最后就上了数列查询这个神奇的网站,竟然被我找到了!!!!就是把题目上给的问题转化为求lcm(1, 2, 3, 4 ...... n-2, n-1, n, n-1) / (n+1),扎扎就打了两个表一个lcm[n

HDU 5407——CRB and Candies——————【逆元+是素数次方的数+公式】

CRB and Candies Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 722    Accepted Submission(s): 361 Problem Description CRB has N different candies. He is going to eat K candies.He wonders how ma

hdu 5407 CRB and Candies(素数筛选法,除法取模(乘法逆元))

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5407 解题思路: 官方题解: The problem is just to calculate g(N) =\ LCM(C(N,0), C(N,1), ..., C(N, N))g(N) = LCM(C(N,0),C(N,1),...,C(N,N)). Introducing function f(n) =\ LCM(1, 2, ..., n)f(n) = LCM(1,2,...,n), the

HDU 5407 CRB and Candies (2015年多校比赛第10场)

1.题目描述:点击打开链接 2.解题思路:本题要求LCM(C(n,0), C(n,1),..., C(n,n)),官方题解是转化为求解LCM(1,2,3,...n+1)/(n+1),然而这种做法还是觉得太陌生,不妨试着用学过的唯一分解定理去做. 首先,求这n+1个数的LCM,实际上就是求所有小于n的素数中,对于每一个素数Pi,哪一项的指数最大,然后把他们连乘起来即可得到LCM值.因此,问题转化为确定每一个pi的最大指数.这里要用到Kummer定理来解决,Kummer定理告诉我们这样一个事实:p恰

【LCM从1-n】 HDU 5407 CRB and Candies

通道 题意:计算C(n,0)+...C(n,n) 思路:转化为LCM(1...n)/ n 代码: #include <cstdio> #include <bitset> using namespace std; typedef long long ll; const int N = 1000000+2; const ll MOD = (ll)1e9 + 7; ll vis[(N+31)/32 + 5]; int pri[5770000], pnum; ll sum[5770000]

HDU 5407 CRB and Candies

传送门 http://oeis.org/A002944 http://oeis.org/A003418 令an=LCM(C(n,0),C(n,1),C(n,2),...,C(n,n)) bn=LCM(1,2,3,...,n) an=bn+1n+1 if (n=pk)bn=p?bn?1elsebn=bn?1 #include <bits/stdc++.h> using namespace std; #define prt(k) cerr<<#k" = "<&

HDU 5411 CRB and Puzzle (2015年多校比赛第10场)

1.题目描写叙述:pid=5411">点击打开链接 2.解题思路:本题实际是是已知一张无向图.问长度小于等于m的路径一共同拥有多少条. 能够通过建立转移矩阵利用矩阵高速幂解决.当中,转移矩阵就是输入时候的邻接矩阵,同一时候多添加最后一列,都置为1.表示从i開始的,长度不超过M的路径的答案总数(最后一行的1~n列为全0行,能够理解为空集),那么把转移矩阵自乘M-1次后就是路径长度为M的转移矩阵(这里的路径长度指的是顶点的个数.顶点=边数+1,因此仅仅须要乘M-1次). 为何便于求和.能够设置

HDU 5414 CRB and String (2015年多校比赛第10场)

1.题目描写叙述:点击打开链接 2.解题思路:本题要求推断字符串s是否能通过加入若干个字符得到字符串t. 首先,能够知道,s必须是t的一个子串(注意:不是连续子串). 第二.因为插入的新字符和它前面的字符c不同.因此假设t中有cnt个连续的c.那么在s中也必须有cnt个连续的c.因此.仅仅要能够满足这2个条件,就一定能够成功实现转化. 那么该怎样做呢?两者能够结合起来推断,用i,j分别表示s,t串中当前扫描的字符的下标.首先从字符串t開始扫描,看第一个字符c是否连续,一直到不连续为止,那么依据上