zoukankan      html  css  js  c++  java
  • 分解因式

    分解因式 jdoj1370-vijos1229

        题目大意:一个自然数n,求出1~20000中第一个约数个数等于n的数,如果大于20000,则输出No Solution。

        注释:n<=80.在此,我们令N=20000

          想法:开始想暴力,一寻思好像没戏。因为如果是极限数据的话,我们首先枚举到20000就是O(N),然后对于每一个数将它质因数分解,时间复杂度就算用pollard_rho也是$O(N^{frac{1}{4}})$,所以总时间复杂度是$O(N^{frac{5}{4}})$,发现... ...哈哈能过啊,哈哈。咳咳,在此我们介绍更优秀的算法。

          我们用快筛欧拉的思想,外层循环枚举2-N,然后对于当前最大的质因数prime[j],我们用epsilon[i]表示i的约数个数。那么epsilon[i*prime[j]]等于什么呢?很容易想到,因为prime[j]是素数,所以,当i%prime[j]不是0是,即gcd(i,prime[j])=1,所以,对于i的任意一个约数k来讲,k*prime[j]都是i*prime[j]的约数,而且,i*prime[j]的每一个约数,都可以分为i的约数或者i的约数乘以prime[j],这种情况我们就讨论完了。

          那如果是prime[j]|i呢?我们考虑,在i*prime[j]中的什么样的约数是i中没有的,我们设$prime[j]^k||i$,那么,如果有一个数是$prime[j]^{k+1}$的倍数而且是i*prime[j]的约数,那么这个数就是i里不存在的。我们期望统计这样的数有多少个(||的意思是恰整除,$j^k|i$中k的最大值)。显然,如果一个数$m*prime[j]^{k+1}|i*prime[j]$,那么$m|(i/prime[j]^k)$。我们设now=$i/prime[j]^k$。那么,显然,epsilon[now]中的任意一个数乘以$prime[j]^{k+1}$都满足题意,我们只需要快筛的时候把i%prime[j]mod到底即可。

        最后,附上丑陋的代码... ...

     1 #include <iostream>
     2 #include <cstdio>
     3 #define N 20000
     4 using namespace std;
     5 int epsilon[N];
     6 int prime[N];
     7 int cnt;
     8 bool v[N];
     9 int main()
    10 {
    11     epsilon[1]=1;
    12     for(int i=2;i<=N;i++)
    13     {
    14         if(!v[i]) prime[++cnt]=i,epsilon[i]=2;
    15         for(int j=1;j<=cnt&&i*prime[j]<=N;j++)
    16         {
    17             v[i*prime[j]]=1;
    18             if(i%prime[j]==0)//这里就用到了上面所叙述的
    19             {
    20                 int now=i;
    21                 while(now%prime[j]==0) now/=prime[j];
    22                 epsilon[i*prime[j]]=epsilon[i]+epsilon[now];//这道水题的精华
    23             }
    24             else
    25                 epsilon[i*prime[j]]=epsilon[i]*2;
    26         }
    27     }
    28     int n;
    29     scanf("%d",&n);
    30     bool flag=false;
    31     for(int i=1;i<=N-10;i++)
    32     {
    33         if(epsilon[i]==n)
    34         {
    35             printf("%d
    ",i);
    36             flag=true;
    37             break;
    38         }
    39     }
    40     if(!flag) printf("NO SOLUTION
    ");
    41     return 0;
    42 }

        小结:我们的想法的切入比较简单,论证上有一些小小的思考而已。

  • 相关阅读:
    多线程伪共享FalseSharing
    C语言restrict限定符
    Linux线程基础函数
    Linux信号函数
    C函数前向声明省略参数
    12.2 关闭DLM 自动收集统计信息 (SCM0)ORA-00600之[ksliwat: bad wait time]
    pdb的数量限制
    关闭或开启memory_target
    OSWATCH安装
    参数SID写错,ERROR OGG-00664 ORA-01034: ORACLE not available ORA-27101: shared memory realm does not exist
  • 原文地址:https://www.cnblogs.com/ShuraK/p/8428488.html
Copyright © 2011-2022 走看看