对1,2,3,……n枚举质因数 你在第一眼看到这道题时估计想:

哎呀我肯定不能for int i = 1;i <= n;i++,while n % i != 0这么枚举有可能除到合数然后wa

反正我是这么想的

后来在@的指点下想到:

欸我从小到大枚举,在n % i != 0 时不断n /= i(即把if改为while,每次先被除掉的一定先是质因数,而和数在枚举到时它的质因数已经全被除掉了,一定不会除到和数,然后记下来而WA

2 comments

  • @ 2025-7-30 11:09:19

    已更正,感谢

    • @ 2025-7-10 22:47:05

      @对不起,给npr磕头,我带错节奏了。

      单纯给n一个数做质因数分解,按以下算法最好O(logn)(比如恰好2的倍数),最差O(n)(n正好是质数),平均O(n)
      for i:1->n
          while(n%i==0)  n/=i
      
      但这题标题是阶乘分解...如果外面套个枚举1->n的循环变O(n^2),爆了
      for num:1->n  
        x = n//n质因数分解过程中会被修改,存一下
        for i:1->n
            while(n%i==0)  n/=i
        n = x//恢复枚举阶乘因子
      
      所以结合素数筛、质因数分解、打表找规律的思想
      我们发现对于7!=1*2*3*4*5*6*7
      质数2是2、4、6的质因数(因数4完全由2处理,2、4、6/2 => 1、2、3)
      质数3是3、6的质因数
      质数5是5的质因数
      质数7是7的质因数
      #include<bits/stdc++.h>
      using namespace std;
      int f(int n,int p){
      	int s=0;
      	while(n){
      		s+=n/p;//质因数分解性质,从小往大枚举质数一定是正解 
      		n/=p;//此处除比乘好在缩小数据范围 
      	}
      	return s;
      }
      int is_prime(int n){
      	for(int i=2;i<=sqrt(n);i++){
      		if(n%i==0) return 0;
      	}
      	return 1;
      }
      int main(){
      	int n;
      	cin>>n;
      	for(int i=2;i<=n;i++){
      		if(is_prime(i)){
      			int k=f(n,i); 
      			if(k==0) break;
      			cout<<i<<" "<<k<<endl;
      		}
      	}
      }
      
      
      • @ 2025-7-10 22:47:58

        脑抽了觉得分解质因数是平均O(logn),忘了质数分布了

      • @ 2025-7-10 23:47:03

        @

        这就像朴素的快排:

        你不搞随机化,别人可以构造数据卡你,O(nlogn)O(n\log n) 硬是退化成 O(n2)O(n^2)

      • @ 2025-7-30 11:13:07

        @

        代码链接

        老师,这个ac了🤔

      • @ 2025-7-31 14:33:10

        undefined@ 🤔啥意思?他nlogn包过呀

    • 1

    Information

    ID
    1122
    Time
    1000ms
    Memory
    256MiB
    Difficulty
    9
    Tags
    # Submissions
    268
    Accepted
    12
    Uploaded By