AcWing 197. 阶乘分解

原题链接

考察:质数筛

错误思路:

        用Map可以很方便地合并同类项,但是用Map会MLE

正确思路:
        对于1~n的每1个数,它们都会被它的最小质因数筛掉.这道题不是求分解n的质数,不能只枚举到√n.因为1~n之间还存在着质数.这些质数能够除尽>√n的质数

        用筛法求出质数后.可以发现1~n的能够分解出质数p的个数是[n/p]个.这个可以分类讨论.实在不懂可以看y总视频.如果n还能除尽p^2.那么在p的基础上再求一次能除尽p^2的个数即可.因为除尽p的已经算了一次,所以求p^2的时候不需要*2

        关于筛法.里层循环的=号非常重要.因为存在N/i=2.2而prime[j]==2的情况,如果没有等号就会少筛

       可以把while循环里的累乘t*=prime[i]换成n/=prime[i]这样不会溢出.

 1 #include <iostream>
 2 #include <cstring>//吾日三省吾身,质数问题考虑1了吗
 3 #include <algorithm>
 4 using namespace std;
 5 const int N = 1e6+10;
 6 int prime[N],cnt,ans[N];
 7 bool st[N];
 8 void GetPrime(int n)
 9 {
10     for(int i=2;i<=n;i++)
11     {
12         if(!st[i]) prime[++cnt] = i;
13         for(int j=1;prime[j]<=n/i;j++)
14         {
15             st[i*prime[j]] = 1;
16             if(i%prime[j]==0) break;
17         }
18     }
19 }
20 int main()
21 {
22     int n;
23     scanf("%d",&n);
24     GetPrime(n);
25     for(int i=1;i<=cnt;i++)
26     {
27         int res = 0;long long t = prime[i];
28         if(t>n) break;
29         while(t<=n)
30         {
31             res+= (long long)n/t;
32             t*=(long long)prime[i];
33         }
34         ans[prime[i]] = res;
35     }
36     for(int i=1;i<=cnt;i++)
37         if(ans[prime[i]]!=0) printf("%d %d\n",prime[i],ans[prime[i]]);
38     return 0;
39 }

 

 

2021.1.24 把这道题又写了一遍,结果WA得非常惨烈,思路是对的,错在要开long long

  1. 这道题不是筛n的质数,而是筛1~n的质数,所以数组要开到1e6,而不是√n
  2. 虽然这道题不用处理1,但一定要注意1
  3. 数论题建议无脑long long.....这道题累乘溢出了
posted @ 2021-01-15 17:29  acmloser  阅读(77)  评论(0编辑  收藏  举报