小红的元素分裂(dp分解因子)

链接:https://ac.nowcoder.com/acm/contest/69117/C
来源:牛客网

小红拿到了一个数组,她每次可以进行如下操作之一:
·选择一个元素\(x\),将其分裂为\(1\)\(x-1\)
·选择一个元素\(x\),将其分裂为\(a\)\(b\),需要保证\(a * b = x\)

小红希望用最少的操作次数,将所有数组的所有元素全部变成\(1\)。你能帮帮她吗?

输入描述:
第一行输入一个正整数\(n\),代表数组的长度。
第二行输入\(n\)个正整数\(a_i\),代表小红拿到的数组。
\(1\leq n,a_i \leq 10^5\)

输出描述:
一个整数,代表最小的操作次数。

示例1
输入
2
2 6
输出
5
说明
第一次,对第一个元素进行第一个操作,数组变成[1,1,6]。
第二次,对第三个元素进行第二个操作,数组变成[1,1,2,3]。
第三次,对第三个元素进行第一个操作,数组变成[1,1,1,1,3]。
第四次,对第五个元素进行第一个操作,数组变成[1,1,1,1,2,1]。
第五次,对第五个元素进行第一个操作,数组变成[1,1,1,1,1,1,1]。

目标是全部变成1,所以我们是1的时候直接初始值为0即可,然后我们发现每一个数可以分裂为两个乘积为x的约数,然后我们直接枚举所有约数即可然后看哪一种情况最优即可

时间复杂度:\(n * sqrt(n)\)

#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=3e5+100; 
int f[maxn];
int main(){
	f[2]=1;
	for(int i=3;i<=1e5;i++){
		f[i]=f[i-1]+1;
		for(int j=2;j*j<=i;j++){
			if(i%j==0){
				f[i]=min(f[i],f[j]+f[i/j]+1);
			}
		}
	}
	int t;
	cin>>t;
	long long int ans=0;
	while(t--){
		int x;
		cin>>x;
		ans+=f[x];
	}
	cout<<ans<<endl;
}
posted @ 2023-11-13 19:36  lipu123  阅读(235)  评论(0)    收藏  举报