zoukankan      html  css  js  c++  java
  • hdu5407 CRB and Candies

    令f(n) = lcm((n, 0), (n, 1),..., (n, n)),

    g(n) = lcm(1, 2,.., n)。

    则有结论:f(n) = g(n + 1) / (n + 1)(证明过程参阅:http://arxiv.org/pdf/0906.2295v2.pdf)。

    待求的是ans = f(n) % mod

    = (g(n + 1) / (n + 1)) % mod

    = (g(n + 1) % mod * Inverse(n + 1) % mod) % mod。

    其中Inverse(n)表示n的关于mod的乘法逆元,即满足Inverse(n) * n % mod = 1。

    由费尔马小定理,amod-1%mod = 1, 于是 a * amod -2 % mod = 1。

    则Inverse(n) = amod-2 %mod(mod 为素数),逆元唯一。

    这样用快速幂很快计算一个数的乘法逆元,下面需要计算g(n)。

    有以下结论g(n) = 

    g(n - 1) * p (如果存在质数p和整数k,满足n = pk)(1),

    g(n - 1) (否则)。

    我们需要预处理出一个对于每个整数其可能对应的p的数组以快速计算g(n)。

    所有的素数存在唯一的p等于其本身和k=1满足式(1)。

    对于任一整数可以写成素数幂的乘积的形式,因此可以用当前素数往后更新。

    http://acm.hdu.edu.cn/showproblem.php?pid=5407

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <algorithm>
     4 
     5 using namespace std;
     6 typedef __int64 LL;
     7 
     8 const int maxn = 1e6 + 10;
     9 const int mod = 1e9 + 7;
    10 
    11 int n;
    12 LL f[maxn], g[maxn];
    13 
    14 LL power(LL a, LL p){
    15     LL ans = 1;
    16     a %= mod;
    17     while(p){
    18         if(p & 1){
    19             ans = (ans * a) % mod;
    20         }
    21         p >>= 1;
    22         a = (a * a) % mod;
    23     }
    24     return ans;
    25 }
    26 
    27 LL Inverse(LL num){
    28     return power(num, mod - 2);
    29 }
    30 
    31 void solve(){
    32     LL ans = f[n + 1] * Inverse(n + 1) % mod;
    33     printf("%I64d
    ", ans);
    34 }
    35 
    36 bool check(int num){
    37     int d = g[num];
    38     while(num % d == 0 && num > 1) num /= d;
    39     return num == 1;
    40 }
    41 
    42 void init(){
    43     for(int i = 1; i < maxn; i++) g[i] = i;
    44     for(int i = 2; i < maxn; i++){
    45         if(g[i] == i){
    46             for(int j = i + i; j < maxn; j += i){
    47                 g[j] = i;
    48             }
    49         }
    50     }
    51     f[0] = 1;
    52     for(int i = 1; i < maxn; i++){
    53         if(check(i)) f[i] = f[i - 1] * g[i] % mod;
    54         else f[i] = f[i - 1];
    55     }
    56 }
    57 
    58 int main(){
    59     init();
    60     int T;
    61     scanf("%d", &T);
    62     while(T--){
    63         scanf("%d", &n);
    64         solve();
    65     }
    66     return 0;
    67 }
    View Code
  • 相关阅读:
    ci高级使用方法篇之连接多个数据库
    JavaSE入门学习17:Java面向对象之package(包)
    找出字符串中第一个出现次数最多的字符
    red5源代码编译并打包公布
    J.U.C--locks--AQS分析
    Spring Web MVC 原理学习(下)
    深入理解 Linux 内存管理
    Java面试问题总结
    盗版者的失落
    eclipse配置lombok插件
  • 原文地址:https://www.cnblogs.com/astoninfer/p/4749409.html
Copyright © 2011-2022 走看看