一,题目
二,思路
(思路基本就一本正经的胡说八道,当时只是举了几个例子,凭着直觉乱写一通,然后莫名其妙的过了)
(1)首先不要管数组p和a,我们可以用一个sum数组,而sum数组每一个数乘起来等于n,而sum数组每一个数组的加和就是我们想要的答案。这时,数组a,p和sum的关系就是,sum中p个相同的数的乘积在数组a中表示为a^p(即a中p个相同的数乘在一起),而sum中多个相同数的加和在数组a中表示为a*p(即a中p个相同的数加在一起)。
说白了,sum中每个数的乘积就是题目中下面的东西
而sum每个数的加和就是题目中的下面的东西
所以题目要我们求的即组成n的因数(这里指乘在一起刚好组成n的所有因数,包括相同的质因数)的和最大是多少,而且这些数中自个的因数必须是质数。
(2)那怎么求出自个的因数是质数的数呢?首先我们先求出n中所有质因数,那么自个的因数是质数的数肯定是这些数的乘积(当然,每个值相同的数只能乘一次)或本身,比如100质因数为2,2,5, 5,那么自个的因数是质数的因数可以是2,2,5,5,10,10,其中2,5是这些数的本身,10是这些数的乘积,好了,求出自个的因数是质数的数的问题解决了。
(3)那怎么求的即组成n的因数(这里指乘在一起刚好组成n的所有因数)的最大和,(开始胡说八道了)首先,根据基本不等式,a*b如果是个定值的话,当a=b时,a+b最小,而a或b越大,说明a+b越大。这时,我们可以将这个性质用于这题(虽然不知道对不对),即组成n的因数(这里指乘在一起刚好组成n的所有因数)中大的因数尽可能大,小的尽可能小。那怎么办呢?我们先求出组成n的质因数(这里指乘在一起刚好组成n的所有质因数,包括相同的质因数),让尽可能多的质因数乘在一起组成数组sum的每一个数,比如864质因数2,2,2,3,3,3,2,2,然后用数组存起来,第一个数组sum里的数是6,第二个是6,第三个是6,第四个是2,第五个是2。这样保证了大的因数尽可能大,小自然会尽可能小,最后将他们加在一起就是所要求的答案了。
(4)当然,我的代码中的求因数和思路有点不同:即sum[i]等于第i个出现在装质因数的数组的所有元素的加和,然后因为直接输出加和,我就用ans直接把所有sum加起来,直接输出答案。而d数组储存了每个质因数a和它的个数p,只要i不大于它的个数,sum就会乘以这个质因数。而MAX用来找出i能够达到的最大值。
#include<deque>
#include<cmath>
#include<iostream>
using namespace std;
#define int long long
struct prime
{
int a,p;
prime(int x,int y):a(x),p(y){};
};
signed main(){
int t;
cin>>t;
while(t--)
{
int num,a=0,p=0,MAX=0, sum=1;
cin>>num;
if(num==1) //如果num是1的话,这个思路的答案是错误的,所以要特判
{
cout<<1<<endl;
continue;
}
deque<prime> d;
for(int i=2;i*i<=num;++i)
{
while(num%i==0) num/=i,a=i,++p;
if(p!=0) d.push_back(prime(a,p));
if(d.size()!=0)MAX=max(d.back().p,MAX);
p=0;
}
if(num>1) d.push_back(prime(num,1)),MAX=max(MAX,1ll);
int ans=0;
for(int i=1;i<=MAX;++i)
{
for(int j=0;j<d.size();++j)
if(d[j].p>=i) sum*=d[j].a;
ans+=sum,sum=1;
}
cout<<ans<<endl;
}
}