zoukankan      html  css  js  c++  java
  • 弹药科技 解题报告

    弹药科技 解题报告

    题目模型:

    假设G(d)表示d的因子个数。已知 F(N)  = N - phi(N) - G(N) + 1。

    求解 F(N!)MOD1000000007 。 N<= 1000000

    原题并不是这样给出的,但是笔者只推到了这个公式,向下就不会做了,所以解题报告就从这里写起。如果真的像上面一样,求F(N)的话,笔者还是有思路的,先求欧拉,再求因子数,再计算,但是这里实在是太。。。居然是N的阶乘,要知道,光20!= 2432902008176640000 了,再来个一百万的阶乘,回家看孩子吧。。

    所以,这个题目要这样建立思路:

    首先,大数据求Mod,一般都要涉及到每步取模,这是一定的,

    其次,要知道要求什么东西,这里涉及 阶乘,欧拉函数和约数个数,所以要想到这几想东西:阶乘,欧拉phi的求法,约数个数定理,

    再向下就要想到这些东西的性质是什么。

    阶乘没什么好说的,for(i <- 1 to n)  fac *= i mod 1000000007;

    重点是要说一下欧拉函数和约数个数定理,首先贴下约数个数定理:

     

    这东西自己百度一下就可以。至于怎么求一个数的约数个数自行百度,其实是笔者比较懒。

    然后要贴一个十分重要的欧拉函数的性质:

    若a是N的质因子,如果(N%a == 0 && (N/a)%a == 0) ,则Euler(N) = Euler(N/a)*a;如果(N%a == 0 && (N/a)%a != 0) 则Euler(N) = Euler(N/a) *(a-1)。有了这个神奇的分式,那么就可以在O(N)的时间内求出N! 的phi了。

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <cstdlib>
     4 #include <algorithm>
     5 #include <iostream>
     6  
     7 using namespace std;
     8 const int lala = 1000000007;
     9 int N;
    10  
    11 long long fac = 1;
    12 int Ans = 0;
    13 int upper = 0,divisor_cnt = 1,euler_phi = 1;
    14 bool vi[1011001];
    15 int prime[1110001];
    16 int c[805005];
    17  
    18 int main(){
    19     cin >> N;
    20      
    21     for(int i = 2;i <= N;++ i){
    22         if(!vi[i]){
    23             ++ upper;
    24             prime[upper] = i;   
    25             for(int j = 2*i;j <= N;j += i)
    26                 vi[j] = true;
    27         }
    28     }   
    29     for(int i = 2;i <= N;++ i)
    30         fac =(long long) (fac*i) % lala;
    31      
    32     long long now_pri;
    33     for(int i = 1;i <= upper;++ i){
    34         now_pri = prime[i];
    35         while(now_pri <= N){
    36             c[i] += N/now_pri;
    37             now_pri = (long long)now_pri * prime[i];
    38         }
    39     }   
    40     for(int i = 1;i <= upper;++ i)
    41         divisor_cnt = divisor_cnt *(long long)(c[i]+1) % lala;
    42      
    43     for(int i = 2;i <= N;++ i)
    44         if(!vi[i])
    45             euler_phi = euler_phi*(long long)(i-1) % lala;
    46         else
    47             euler_phi = euler_phi*(long long)i % lala;
    48              
    49     Ans = fac - euler_phi - divisor_cnt + 1;
    50     while(Ans < 0)
    51         Ans += lala;
    52          
    53     cout << Ans;
    54     return 0;
    55 }
    View Code
  • 相关阅读:
    【杭电】[1874]畅通工程续
    【杭电】[2544]最短路
    【杭电】[1087]Super Jumping! Jumping! Jumping!
    【HPU】[1689]MZY寻宝
    【杭电】[1495]非常可乐
    【杭电】[1242]Rescue
    【杭电】[1787]GCD Again
    【算法】欧拉函数——小于n的数中与n互质数的数目
    【HPU】[1738]Stack ? Queue ?
    【HPU】[1737]老王特警队
  • 原文地址:https://www.cnblogs.com/sxprovence/p/4718227.html
Copyright © 2011-2022 走看看