花了四小时才琢磨透了细节原理
2026-09-13 21:38:46
发布于:广东
15阅读
0回复
0点赞
/*
主要思路:若果两个数相等,那么质因数分解一定相同,因此把每个数进行因数分解,再根据各个数 相同的质因数的个数来决定 补或删。
10 : 2 5
6 : 2 3
35 : 5 7
105: 3 5 7
42 : 2 3 7
2310:2 3 5 7 11
8 : 2 2 2
把上面这个样例分解完后,发现 '2' 这个因数,只有35,105 没有,所以是给这两个数各补一个'2' 比 把其余五个数各删除一个'2' 更省金币;
2310这个数有个'11'质因数是其他数没有的,删除'11'更省金币;
8 有3个‘2’因数,很显然 把多的两个‘2’删掉,比其他数 补两个 '2'更省金币;
其他质因数同理。
具体过程:
把每个数的 各质因数出现的次数统计出来(记作c),就能根据 min((n-c),c)决定补还是删;
举例子:min((7-5), 5) --> (7-5)个数中缺一个质因数'2' , 5个数有'2' ,决定花(7-5)个金币为35、105各补上‘2’;
以下是统计各质因数出现的次数:
1 2 3 //质因数出现的次数
----------
2 | 5 1 1 //1个‘2’在5个数中出现,2个‘2’在1个数中出现,3个‘2’在1个数中出现
3 | 4 0 0 //1个‘3’在4个数中出现,没有数出现2个‘3’,没有数出现3个‘3’
4 | 0 0 0 //4是合数,合数是不会出现在质因数分解中
5 | 4 0 0 //1个'5',在4个数中出现
6 | 0 0 0
7 | 4 0 0 //1个'7',在4个数中出现
8 | 0 0 0
9 | 0 0 0
10| 0 0 0
11| 1 0 0 //1个'11',在1个数中出现
特别注意:题目指定P只能质数。8既含1个'2',也含2个'2',也含3个'2',
在验证哪些数含2个‘2’的时候,只有8满足,花1金币删掉1个2;再往后验证哪些数含3个‘2’的时候,再花1金币删掉1个2;
总体来看就是花了2金币删了8中的2个'2’
*/
#include<bits/stdc++.h>
using namespace std;
int n;
int a;
int ans;
int arr[100005][20];//行是质因数,列是质因数出现的次数;实际需要17列就够,因为2^17就能比1e5大
int fun(int x){
if(x==1) return 0;
for(int i=2;i*i<=x;i++){
int cnt=0;
while(x%i==0){
arr[i][++cnt]++; //[质因数][出现的次数]出现cnt次质因数的数字个数
x/=i;
}
}
if(x>1){ //不能被分解的,那本身就是个质数
arr[x][1]++;
}
return 0;//踩坑,不写返回值会TLE
}
int main(){
cin>>n;
for(int i=1;i<=n;i++){
cin>>a;
fun(a);
}
for(int i=2;i<=100000;i++){
for(int j=1;j<20;j++){
if(arr[i][j]==0) break; //合数或质因数出现次数为0的部分就可换行
ans+=min(n-arr[i][j],arr[i][j]);
}
}
cout<<ans;
}
这里空空如也

有帮助,赞一个