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
- 这道题不是筛n的质数,而是筛1~n的质数,所以数组要开到1e6,而不是√n
- 虽然这道题不用处理1,但一定要注意1
- 数论题建议无脑long long.....这道题累乘溢出了