题目描述
Hanks 博士是BT (Bio-Tech,生物技术) 领域的知名专家。现在,他正在为一个细胞实 验做准备工作:培养细胞样本。
Hanks 博士手里现在有N 种细胞,编号从1~N,一个第i 种细胞经过1 秒钟可以分裂为 Si 个同种细胞(Si 为正整数)。现在他需要选取某种细胞的一个放进培养皿,让其自由分裂, 进行培养。一段时间以后,再把培养皿中的所有细胞平均分入M 个试管,形成M 份样本, 用于实验。Hanks 博士的试管数M 很大,普通的计算机的基本数据类型无法存储这样大的 M 值,但万幸的是,M 总可以表示为m1 的m2 次方,即M =m1^m2 ,其中m1,m2 均为基本 数据类型可以存储的正整数。
注意,整个实验过程中不允许分割单个细胞,比如某个时刻若培养皿中有4 个细胞, Hanks 博士可以把它们分入2 个试管,每试管内2 个,然后开始实验。但如果培养皿中有5 个细胞,博士就无法将它们均分入2 个试管。此时,博士就只能等待一段时间,让细胞们继 续分裂,使得其个数可以均分,或是干脆改换另一种细胞培养。
为了能让实验尽早开始,Hanks 博士在选定一种细胞开始培养后,总是在得到的细胞“刚 好可以平均分入M 个试管”时停止细胞培养并开始实验。现在博士希望知道,选择哪种细 胞培养,可以使得实验的开始时间最早。
输入
第一行有一个正整数 N,代表细胞种数。
第二行有两个正整数 m1,m2,以一个空格隔开,m1^ m2 即表示试管的总数M。
第三行有 N 个正整数,第i 个数Si 表示第i 种细胞经过1 秒钟可以分裂成同种细胞的个 数。
输出
共一行,为一个整数,表示从开始培养细胞到实验能够开始所经过的 最少时间(单位为秒)。 如果无论 Hanks 博士选择哪种细胞都不能满足要求,则输出整数-1。
样例输入
样例输入1 1 2 1 3 样例输入2 2 24 1 30 12
样例输出
-1 【输入输出样例1 说明】 经过 1 秒钟,细胞分裂成3 个,经过2 秒钟,细胞分裂成9 个,……,可以看出无论怎么分 裂,细胞的个数都是奇数,因此永远不能分入2 个试管。 2 【输入输出样例2 说明】 第 1 种细胞最早在3 秒后才能均分入24 个试管,而第2 种最早在2 秒后就可以均分(每 试管144/(241)=6 个)。故实验最早可以在2 秒后开始。
数据范围限制
【数据范围】
对于 50%的数据,有m1^m2 ≤ 30000。
对于所有的数据,有1 ≤N≤ 10000,1 ≤m1 ≤ 30000,1 ≤m2 ≤ 10000,1 ≤ Si ≤ 2,000,000,000。
解析
这一道题目可以看出来:这个数字是非常大的所以我们不可能把它转化为long long 然后直接暴力。所以,动用你们聪明的脑袋瓜想一想,让一个数整除另一个数的方法。
这里我就在比赛时想到了分解质因数,这是一个AC的方法,对于一个整数而言,他是可以被分解的,如 12 = 2*2*3 , 24 = 2*2*2*3 , 23 = (1*)23 ……
思考比对一下 12和24的质因数 (因为它们是倍数关系)
在这里,已经很明显了, 24 / 12 = (2*2*2*3) / (2*2*3)
= 2*2*2*3 / 2 / 2 / 3
只要24的因数12都有,那么它们就可以整除!
所以,我们可以把这个巨大的数分解质因数(方法就是在不看幂的基础上把原数m1分解,然后把他的每一个因数个数*m2),然后把细菌数分解,如果细菌数没有原数的所有出现过的质因数,直接答案为-1,否则
用一个mx表示需要时间的最小值(两个判断可以同时进行): 使用原数的质因数除以细菌数的对应的质因数(向上取整)(除到数字为0) 除的次数取最大值 然后与mx取最大值
上代码
代码
#include <bits/stdc++.h>
using namespace std;
int n,xb[10010],m1,m2,last=0;
int fj[30010]={0};
int max(int a,int b)
{
return a>b?a:b;
}
int main()
{
freopen("cell.in","r",stdin);
freopen("cell.out","w",stdout);
scanf("%d",&n);
scanf("%d%d",&m1,&m2);
while(m1)
{
int sqr = sqrt(m1);
bool bflag = 1;
for(int i=2;i<=sqr&&bflag;i++)
{
while(m1%i==0)
{
fj[i]+=m2;
bflag=0;
m1 /= i;
last=max(last,i);
}
}
if(bflag) {
if(m1) fj[m1]+=m2;
last = max(last,m1);
break;
}
}
int minn = 99999999;
for(int i=1;i<=n;i++)
{
int x;
scanf("%d",&x);
int maxx = 0;
for(int j = 2;j <= last;j++)
{
if(fj[j])
{
int p = 0;
while(x%j==0&&x){
p++;
x/=j;
}
if(!p) {
maxx = 99999999;
break;
}
maxx = max(maxx,ceil(1.0*fj[j]/p));
}
}
if(minn > maxx) minn = maxx;
}
if(minn==99999999)
printf("-1\n");
else printf("%d\n",minn);
return 0;
}