• hdu 5407 CRB and Candies(组合数+最小公倍数+素数表+逆元)2015 Multi-University Training Contest 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
    ", anss[n]);
    77     }
    78     return 0;
    79 }
    View Code

     

  • 相关阅读:
    上经 -- 乾【卦一】乾为天(三)
    上经 -- 乾【卦一】乾为天(一)
    8. Shell 文件包含
    7. Shell 函数
    6. Shell 流程控制
    5. test命令
    4. printf 命令
    3. Shell 基本运算符
    2. Shell 传递参数
    shell介绍
  • 原文地址:https://www.cnblogs.com/mypride/p/4748382.html
Copyright © 2020-2023  润新知