codechef Chef and easy problem 2

Problem Description

Roma gave Chef an array of intergers.
Chef wants to make all integers in the array equal to 1.
In a single operation, he can select a prime number p and a subset of the integers, and then divide all of the integers in the subset by p.
Chef can make this operation only if every integer in the selected subset is divisible by p.

Please help Chef to make all the integers in the array equal to 1 with minimum number of operations.

Input

The first line of input contains a single integer T denoting the number of test cases. The description of Ttest cases follows.

The first line of each test case contains a single integer N denoting the length of the array that Roma gave Chef.

The second line contains N space-separated integers A1A2, ..., AN denoting the integers in the array.

Output

For each test case, output a single line containing one integer - the minimum number of operations needed to make all numbers equal to 1.

Constraints

  • Subtask 1 (10 points): T = 5, 1 ≤ N ≤ 105, 1 ≤ Ai ≤ 3
  • Subtask 2 (40 points): T = 3, 1 ≤ N ≤ 10, 1 ≤ Ai ≤ 106
  • Subtask 3 (50 points): T = 3, 1 ≤ N ≤ 105, 1 ≤ Ai ≤ 106

Example

Input:

1 3 1 2 4

Output:

2

题解

素数筛法+分解质因数。O(n)的筛法可以顺便找出最小质因数。

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<iostream>
#include<algorithm>
#define ll long long
#define MAXN 1000002
using namespace std;
int T,n,a[100002];//1000000
int mn[MAXN],pri[MAXN],zz;
int num[MAXN];
void prime()
{
	int i,j;
	for(i=2;i<=1000000;i++)
	   {if(!mn[i])
		   {mn[i]=i; zz++; pri[zz]=i;}
		for(j=1;j<=zz&&pri[j]*i<=1000000;j++)
		   {mn[pri[j]*i]=pri[j];
			if(i%pri[j]==0)break;
		   } 
	   }
}
void init()
{
	scanf("%d",&n);
	int i;
	for(i=1;i<=n;i++) scanf("%d",&a[i]); 
}
void work()
{
	int i,j,s,ct; ll ans=0;
	memset(num,0,sizeof(num));
	for(i=1;i<=n;i++)
	   {while(a[i]!=1)
	      {s=mn[a[i]]; ct=0;
		   while(a[i]%s==0) {a[i]/=s; ct++;}
		   num[s]=max(num[s],ct);
		  }
	   }
	for(i=2;i<=1000000;i++)
	   ans+=num[i];
	printf("%lld\n",ans);
}
int main()
{
	prime();
	scanf("%d",&T);
	while(T--) {init(); work();}
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值