细胞分裂

D- 细胞分裂

题目链接

题意:

​ 输入 n,表示有n种细胞,数量为S-i,每秒分裂一次,每次分裂后的数量为原来的S-i倍。输入m1,m2,m1^m2表示试管个数。输入n种细胞最初始状态下的数量S-i。求哪一种细胞,经过最短的天数后,能过均匀的分布在所有试管中。输出最短天数。

解题思路:

​ 由于由于级数过大。可以考虑质因数分解做法。将m1质因数分解,并保存所有质因数的个数与m2相乘的结果。m1m2即等于,所有m1所有质因数(个数*m2)的乘积。

​ 同理,将细胞初始状态数,进行质因数分解,并记录每一个质因数的个数。

​ 两个数相除,即是,所有 被除数质因数^(被除数的质因数的指数-除数质因数的指数)的乘积。

​ 所以易知道,要使得能过均匀分布,即是能整除,即是相除后,被除数质因数的指数为非负整数即可。具体实现与细节请看代码注释。

AC代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int n,m1,m2,s,a[30100],b[30100],max_,min_=INT_MAX-1,pos_,pos,d;
void zhi(int m,int a[]){//质因数分解。 
	if(m<=1)return ;
	int flag=0;
	for(int i=2;i<=m&&i<=30000;i++){// m1<=30000,所以i<=30000; 
        while(m!=i){
		    if(m%i==0){//若是质因数。 
	           	a[i]++;
		        m=m/i;
		    }
		    else break;
		}
		if(i==m)a[i]++;
		pos_=max(i,pos_);//最大质数,用来确定后面遍历比较的上界。 
    }
}
int main(){
	cin>>n;
	cin>>m1>>m2;//总数为m1^m2 
	memset(a,0,sizeof(a));//初始化。 
	zhi(m1,a);//将底数m1质因数分解,记录某个因数的个数,并保存在数组a中。	
	pos=pos_;//最大因数,用于后面循环遍历的上界 
	for(int i=0;i<=pos;i++){
		a[i]*=m2;//由于是m1^m2,所以,即使有m2个m1相乘,则将每个因数的个数乘以m2. 
	} 
	int flag=0,n_=n;
	while(n--){//输入n个数 
		int flag2=0;
		memset(b,0,sizeof(b));//初始化b数组。 
		max_=1;
		cin>>s;
		zhi(s,b);//将最初的倍数s质因数分解,记录每一个因数的个数,并保存在数组b中。 
		for(int i=2;i<=pos+1;i++){
			if(a[i]!=0&&b[i]==0){//如若,最初倍数s的因数中没有m1^m2的因数相对应,则永远除不尽。直接跳出循环 
				flag++;
				flag2=1;
				break;
			}else if(a[i]==0&&b[i]==0||(a[i]<=b[i])){//s与m1^m2都无此质因数。直接跳过。 
				continue;
			}
			d=a[i]/b[i]+(a[i]%b[i]!=0);//向上取整。 
			max_=max(d,max_);//维护最大值,即最大满足条件。 
		}
		if(flag2!=1)min_=min(min_,max_);//维护最大值的最小值。 
	}
	if(m1==1){//特殊情况 
		cout<<0<<endl;
		return 0;
	} 
	if(flag==n_)cout<<-1<<endl;//若全都不能除尽,则输出-1 
	else cout<<min_<<endl;//输出最小值。 
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值