P1069 [NOIP2009 普及组] 细胞分裂题解

题目

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​,以一个空格隔开,即表示试管的总数​​M=m1^{m2}

第三行有N个正整数,第i个数Si​表示第i种细胞经过1秒钟可以分裂成同种细胞的个数。

输出格式

一个整数,表示从开始培养细胞到实验能够开始所经过的最少时间(单位为秒)。

如果无论Hanks博士选择哪种细胞都不能满足要求,则输出整数−1。

输入输出样例

输入样例

1 
2 1 
3

输出样例

-1

解析

这里补充一下算术基本定理的知识。

一个整数可以被表示成若干质数的乘积。这样就可以从一个新的角度来看待整数:正整数都是由质数为基底“构筑”的(1可以被视作零个质数的乘积)。如果把质数想象成元素(原子),把:原子结合”的动作解释成乘法,那么可以把质数合成出所有大于1的整数。

算术基本定理:设a>1,那么必有a=p1^{a1}p2^{a2}\cdots ps^{as},其中Pj(1<=j<=s)是两两不相同的质数,aj(1<=j<=s)表示对应质数的幂次(出现的次数)。若在不记次序的意义下,该分解式是唯一的

算术基本定理其实就是平时所说的分解质因数的过程,朴素的分解质因数的代码如下:

int Decomposition(int x,int a[]){
	int cnt=0;
	for(int i=2;i<=x/i;i++){
		for(;x%i==0;x/=i){
			a[++cnt]=i;
		}
	}
	if(x>1){
		a[++cnt]=x;
	}
	return cnt;
}

下面给出一些算术基本定理的常用推论

推论1 d是a的约数的充要条件是d=p1^{e1}p2^{e2}\cdots ps^{es},0<=ej<=aj,1<=j<=s,即d中每个质数的幂次都不超过a的。

推论2b=p1^{b1}p2^{b2}\cdots ps^{bs}(这里允许某些aj或bj为0),那么\left ( a,b \right )=p1^{c1}p2^{c2}\cdots ps^{cs}cj=min(aj,bj),以及[a,b]=p1^{d1}p2^{d2}\cdots ps^{ds},dj=max\left ( aj,bj \right ).

推论3 用除数函数\tau \left ( \alpha \right )表示\alpha的所有正约数的个数,则\tau \left ( \alpha \right )=\left ( a1+1 \right )\cdots \left ( as+1 \right )=\tau \left ( p1^{\alpha 1} \right )\cdots \tau\left ( p1^{\alpha 1} \right )。这个推论更像是推论1的推论,对于每个质因子上的幂次,可以取0到ai中的任意整数,共ai+1个。由乘法原理可以直接得出。

比如,a=2^{7}\times 3^{8}\times 5^{9},可以直接写出a的质因子个数=\left ( 7+1 \right )\left ( 8+1 \right )\left ( 9+1 \right )=8\times 9\times 10=720

推论4 用除数和函数\sigma \left ( \alpha \right )表示\alpha的所有正约数的和,则\sigma \left ( \alpha \right )=\frac{p1^{a1+1}-1}{p1-1}\cdots \frac{p1^{a1+1}-1}{p1-1}=\sigma \left ( p1^{\alpha 1} \right )\cdots \sigma \left ( p1^{\alpha s} \right )

这个推论也是推论1的推论,但是比起推论3用到了更高级的乘法原理。比如,可以知道\alpha =120=2^{3}\times 3\times 5的因子分别是1,2,3,4,5,6,8,10,12,15,20,24,30,40,60,120。

然后用等比数列求和公式\left ( \frac{p1^{a1+1}-1}{p1-1}=1+p1+\cdots +p1^{\alpha 1} \right )展示那个算式\alpha \left ( 120 \right )=\frac{2^{4}-1}{2-1}\frac{3^{2}-1}{3-1}\frac{5^{2}-1}{5-1}=\left ( 2^{3} +2^{2}+2^{1}+1\right )\left ( 3^{1} +1\right )\left ( 5^{1} +1\right )

最后再把括号展开,发现\sigma \left ( 120 \right )=\left ( 2^{3}+2^{2} +2^{1}+1\right )\left ( 3^{1}+1 \right )\left ( 5^{1} +1\right )=120+24+40+8+60+12+20+4+30+6+10+2+15+3+5+1

针对虽说关键数字m1^{m2}大得吓人,但若是有推论1的铺垫,这道题的突破点是十分明显的:如果m1=p1^{\alpha 1}p2^{\alpha 2}\cdots ps^{as},那么m1^{m2}=p1^{a1m2}p2^{a2m2}\cdots ps^{asm2}。接下来只需要解决题意中的x_{i}的求解。

由推论1可以得到,当m1^{m2}中的每个质因子的幂次都比S_{i}^{x_{i}}小时,m1^{m2}|S_{i}^{x_{i}}成立。S_{i}^{x_{i}}中的质因子是否出现由S_{i}决定,而质因子出现了几次主要由x_{i}决定。若S_{i}=p1^{e1}p2^{e2}\cdots p_{s}^{e}p_{s+1}^{e_{s}+1}\cdots p_{s+r}^{e_{s+r}},那么xi应该使得对于所有1<=j<=s的j,满足a_{j}m_{2}\leqslant e_{j}x_{i}.

所以从m_{1}中的每个质因子p_{j}出发:如果这个S_{i}不能整除p_{j},则说明S_{i}不包含p_{j}这个质因子,进而说明找不到题设要求的x_{i};如果这个S_{i}能整除p_{j},那么只要求出对应的e_{j},就能算出第j个质因子,要求x_{i}不小于\left \lceil \frac{a_{j}m_{2}}{e_{j}} \right \rceil,再对所有这样的要求取最大值,就得到了x_{i},最后对所以合法的x_{i}取最小值就是答案。

#include<cstdio>
#include<algorithm>
using namespace std;
#define maxn 10010
int m1,m2,n,pri[maxn],tot[maxn],a[maxn];
int Decomposition(int x){
	int cnt=0,Cnt=0;
	for(int i=2;i<=x/i;i++){
		for(;x%i==0;x/=i){
			a[++cnt]=i;
		}
	}
	if(x>1){
		a[++cnt]=x;
	}
	for(int i=1;i<=cnt;i++,tot[Cnt]++){//tot记录对应质数的次数 
		if(a[i]!=a[i-1]){//pri记录m1中出现的次数 
			pri[++Cnt]=a[i];
		}
	}
	return Cnt;
}
int main(){
	scanf("%d%d%d",&n,&m1,&m2);
	int cnt=Decomposition(m1),ans=2e9,s;
	while(n--){
		scanf("%d",&s);
		int x=0;
		for(int i=1;i<=cnt;i++){
			int p=pri[i];
			if(s%p!=0){
				x=-1;
				break;
			}
			else{
				int e=0;
				for(;s%p==0;s/=p){
					e++;
				}
				x=max(x,1+(m2*tot[i]-1)/e);
			}
		}
		if(x>=0){
			ans=min(x,ans);
		}
	}
	if(ans>=2e9){
		puts("-1");
	}
	else{
		printf("%d",ans);
	}
	return 0;
}
  • 30
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

互联网的猫

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值