数论 HDOJ 5407 CRB and Candies

题目传送门

题意:求LC(C(N,0),C(N,1),...,C(N,N)),LCM是最小公倍数的意思,C函数是组合数。

分析:先上出题人的解题报告

  

  好吧,数论一点都不懂,只明白f (n + 1)意思是前n+1个数的最小公倍数,求法解释参考HDOJ 1019,2028

这个结论暂时不知道怎么推出来的,那么就是剩下1/(n+1) 逆元的求法了

代码:

/************************************************
* Author        :Running_Time
* Created Time  :2015-8-21 14:52:39
* File Name     :B.cpp
 ************************************************/
 
#include <cstdio>
#include <algorithm>
#include <iostream>
#include <sstream>
#include <cstring>
#include <cmath>
#include <string>
#include <vector>
#include <queue>
#include <deque>
#include <stack>
#include <list>
#include <map>
#include <set>
#include <bitset>
#include <cstdlib>
#include <ctime>
using namespace std;
 
#define lson l, mid, rt << 1
#define rson mid + 1, r, rt << 1 | 1
typedef long long ll;
const int N = 1e6 + 10;
const int INF = 0x3f3f3f3f;
const int MOD = 1e9 + 7;
ll f[N];
int p[N];
 
bool ok(int n)  {
    int t = p[n];
    while (n % t == 0 && n > 1) n /= t;
    return n == 1;
}
 
void seive(int n)   {
    for (int i=1; i<=n; ++i)    p[i] = i;
    for (int i=2; i<=n; ++i)    {
        if (p[i] == i)    {
            for (int j=2*i; j<=n; j+=i) p[j] = i;
        }
    }
}
 
ll pow_mod(int a, int x, int p) {
    ll ret = 1;
    while (x)   {
        if (x & 1)  ret = ret * a % p;
        a = a * 1ll * a  % p;
        x >>= 1;
    }
    return ret;
}
 
ll Inv(int a)   {
    return pow_mod (a, MOD - 2, MOD);
}
 
void solve(void)    {
    seive (1000010);
    f[0] = 1;
    for (int i=1; i<=1000010; ++i)  {
        if (ok (i))    {
            f[i] = f[i-1] * p[i] % MOD;
        }
        else    f[i] = f[i-1];
    }
}
 
int main(void)    {
    solve ();
    int T;  scanf ("%d", &T);
    while (T--) {
        int n;  scanf ("%d", &n);
        printf ("%I64d
", f[n+1] * Inv (n + 1) % MOD);
    }
 
    return 0;
}

  

编译人生,运行世界!
原文地址:https://www.cnblogs.com/Running-Time/p/4748917.html