hihocoder 1165 : 益智游戏(素数的处理模板)

幽香今天心情不错,正在和花田里的虫子玩一个益智游戏。
这个游戏是这样的,对于一个数组A,幽香从A中选择一个数a,虫子从A中选择一个数b。a和b可以相同。她们的分数是a*b的因子的个数。
幽香和虫子当然想要获得尽可能的高的分数,你能告诉她们应该选择哪两个数吗。
由于幽香是个非常随意的人,数组A中的元素都是她随机选择的。

输入

一行一个数n,表示A中整数的数量。
接下来一行n个数,分别表示a1,a2,...,an,为A中的元素。

n <= 100000, 1 <= ai <= 100000
保证所有的ai都是随机生成的。

输出

一行表示最大的分数。

样例输入
2
3 4
样例输出
6
http://hihocoder.com/problemset/problem/1165?sid=415097

知识点:一个数的因子数等于它完全分解为质数后,每一项质数个数加一连乘的结果。比如75=3*5*5,那么它的因子数为(1+1)*(2+1)=6。其实这个结论特别好证明,每一个因子数可以取0到它的个数个。比如,每个都取0个,那么结果即为1。如果每个都取,那么结果为那个数本身。

预处理下1-100000的因子数,然后将读进来的数按因子数多少排个序,然后取其前n(当n<100)或者前100个计算,取最大值即可。

#include<iostream>  
#include<algorithm>  
#include<string>  
#include<map>  
#include<vector>  
#include<cmath>  
#include<queue>  
#include<string.h>  
#include<stdlib.h>  
#include<cstdio>  
#define ll long long  
using namespace std;  
struct node{
	int a,b,c;  //a代表质因子的种类数 b代表质因子总的个数  
};
node y[100010];
int num[105];
int cmp(node p,node q){
	if(p.a!=q.a)
		return p.a>q.a;
	else
		return p.b>q.b;
}
ll cal(ll x){     //很好的求因子个数的模板 
    memset(num,0,sizeof(num));  
    int cnt=0;  
    for(ll i=2;i*i<=x;i++){  
        if(x%i==0){  
            cnt++;  
            while(x%i==0){  
                num[cnt]++; x/=i;  
            }  
        }  
    }  
    if(x>1) num[++cnt]++;  
    ll res=1;  
    for(int i=1;i<=cnt;i++){  
        res*=(num[i]+1);  
    }  
    return res;  
}
int main(){
	int n;
	while(scanf("%d",&n)!=EOF){
		for(int i=0;i<n;++i){
			cin>>y[i].c;
			int p=y[i].c;
			y[i].a=0;y[i].b=0;
			for(int j=2;j*j<=p;++j){ //求素因子种类和个数的模板 
				if(p%j==0){
					y[i].a++;
					while(p%j==0){
						y[i].b++;
						p/=j;
					}
				}
			}
			if(p>1){
				y[i].a++;
				y[i].b++;
			}
		}
		sort(y,y+n,cmp);
		ll max=0;
		for(int i=0;i<min(n,100);++i){
			for(int j=i;j<min(n,100);++j){
				ll w=cal((ll)y[i].c*y[j].c); //特别要注意这里的(ll) 
				if(w>max)
					max=w;
			}
		}
		cout<<max<<endl;
	}
    return 0;
} 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值