zoukankan      html  css  js  c++  java
  • ACM学习历程—HDU5407 CRB and Candies(数论)

    Problem Description

    CRB has N different candies. He is going to eat K candies.
    He wonders how many combinations he can select.
    Can you answer his question for all K (0 ≤ K ≤ N )?
    CRB is too hungry to check all of your answers one by one, so he only asks least common multiple(LCM) of all answers.

    Input

    There are multiple test cases. The first line of input contains an integer T , indicating the number of test cases. For each test case there is one line containing a single integer N .
    1 ≤ T ≤ 300
    1 ≤ N ≤ 106 

    Output

    For each test case, output a single integer – LCM modulo 1000000007(109+7 ).

    Sample Input

    5

    Sample Output

    12 

    10

    题目要求的是所有C(n, i) (0 <= i <= n)的最小公倍数。

    这题如果直接用LCM去求会T掉,

    就算离线所有n!的逆元复杂度是O(n)

    然后for循环C(n, i)O(n)

    然后用LCM求最小公倍数是O(log(a)),最差情况接近O(log(10^9+7)) ~ 30

    所以复杂度最差是O(30n), 300组数据,最终需要O(10^10)左右。

    那个30不乘的话O(3*10^8)左右。卡了一个常数倍数量级。

    max(Vp(C(n, i))) = max(Vp(i+1)) - Vp(n+1) (0 <= i <= n)

    有了这个式子,就证明了[C(n, 0), C(n, 1) ,.....C(n, n)] = [1, 2, ....,n+1]/(n+1)

    等式两侧的质因子指数相等,自然等式就相等了。

    然后最终结果是所有p^maxN/p^k的乘积(其中maxN是pn+1内的最高次数,k是p能整除n+1的最高次数)

    也就是所有p^maxN的乘积除以p^k的乘积,分子等于[1, 2, 3,....n+1],分母等于n+1

    这个结果和题解的结论是一致的。

    证明过程有点搓。。。。

    如果顺序找到kmaxN的话,复杂度是O(num*log(p)),其中num是素数个数,p是素数。

    如果二分查找的话,是O(num*log(logp))

     

    此外托人找了另一种证明方式,很巧妙:

     

    代码:O(num*log(p))

     

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <cmath>
    #include <set>
    #include <map>
    #include <queue>
    #include <string>
    #include <algorithm>
    #define LL long long
    
    using namespace std;
    
    const LL MOD = 1e9+7;
    const int maxN = 1e6+5;
    bool isprim[maxN];
    int n, prim[maxN], top;
    
    //埃氏筛法求素数
    void isPrim()
    {
        memset(isprim, true, sizeof(isprim));
        isprim[0] = isprim[1] = false;//初始化
        for (LL i = 2; i < maxN; ++i)//筛法
        {
            if (isprim[i])
            {
                for (LL j = i*i; j < maxN; j += i)//上界太大可能会爆int
                {
                    isprim[j] = false;
                }
            }
        }
    }
    
    void init()
    {
        isPrim();
        top = 0;
        for (int i = 2; i < maxN; ++i)
            if (isprim[i])
                prim[top++] = i;
    }
    
    void work()
    {
        LL ans = 1;
        for (int i = 0; i < top && prim[i] <= n+1; ++i)
        {
            for (LL v = prim[i]; v <= n+1; v *= prim[i])
            {
                if ((n+1)%v)
                    ans = (ans*prim[i])%MOD;
            }
        }
        printf("%I64d
    ", ans);
    }
    
    int main()
    {
        //freopen("test.in", "r", stdin);
        init();
        int T;
        scanf("%d", &T);
        for (int times = 0; times < T; ++times)
        {
            scanf("%d", &n);
            work();
        }
        return 0;
    }

     

     

  • 相关阅读:
    学习python报错处理
    Java命名规则
    python打开文件可以有多种模式
    python中的异常
    python中的构造函数和构造函数和析构函数的作用
    学习网址
    使用Python+selenium过程中所需安装的库和软件
    oracle 、server和my sql 语法区别
    blob(斑点)特征,SimpleBlobDetector(OpenCV案例源码detect_blob.cpp解读)
    查找与绘制轮廓findContours()、drawContours()(OpenCV案例源码contours2.cpp解读)
  • 原文地址:https://www.cnblogs.com/andyqsmart/p/4756707.html
Copyright © 2011-2022 走看看