1947:【09NOIP普及组】细胞分裂

【题目描述】

Hanks 博士是BT (Bio-Tech,生物技术) 领域的知名专家。现在,他正在为一个细胞实验做准备工作:培养细胞样本。

Hanks 博士手里现在有NN 种细胞,编号从1∼N1∼N,一个第ii 种细胞经过11 秒钟可以分裂为SiSi 个同种细胞(SiSi 为正整数)。现在他需要选取某种细胞的一个放进培养皿,让其自由分裂,进行培养。一段时间以后,再把培养皿中的所有细胞平均分入MM 个试管,形成MM 份样本,用于实验。Hanks 博士的试管数MM 很大,普通的计算机的基本数据类型无法存储这样大的MM 值,但万幸的是,MM 总可以表示为m1m1 的m2m2 次方,即M=m1m2M=m1m2,其中m1m1,m2m2 均为基本数据类型可以存储的正整数。

注意,整个实验过程中不允许分割单个细胞,比如某个时刻若培养皿中有44 个细胞,Hanks 博士可以把它们分入22 个试管,每试管内22个,然后开始实验。但如果培养皿中有55个细胞,博士就无法将它们均分入22个试管。此时,博士就只能等待一段时间,让细胞们继续分裂,使得其个数可以均分,或是干脆改换另一种细胞培养。

为了能让实验尽早开始,Hanks 博士在选定一种细胞开始培养后,总是在得到的细胞“刚好可以平均分入MM 个试管”时停止细胞培养并开始实验。现在博士希望知道,选择哪种细胞培养,可以使得实验的开始时间最早。

【输入】

共有三行。

第一行有一个正整数 NN,代表细胞种数。

第二行有两个正整数 m1m1,m2m2,以一个空格隔开, m1m2m1m2即表示试管的总数MM。

第三行有 NN 个正整数,第ii 个数SiSi 表示第ii 种细胞经过11 秒钟可以分裂成同种细胞的个数。

【输出】

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

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

【输入样例】

1
2 1
3

【输出样例】

-1

【提示】

【输入输出样例1 说明】

经过11秒钟,细胞分裂成33个,经过22 秒钟,细胞分裂成99个,……,可以看出无论怎么分裂,细胞的个数都是奇数,因此永远不能分入22个试管。

【输入输出样例 2】

输入:

2
24 1
30 12

输出:

2

【输入输出样例2 说明】

第 11 种细胞最早在33 秒后才能均分入2424 个试管,而第22 种最早在22 秒后就可以均分(每试管144/(241)=6144/(241)=6 个)。故实验最早可以在22秒后开始。

【数据范围】

对于 50%的数据,有m1m2≤30000m1m2≤30000。

对于所有的数据,有1≤N≤10000,1≤m1≤30000,1≤m2≤10000,1≤Si≤2,000,000,0001≤N≤10000,1≤m1≤30000,1≤m2≤10000,1≤Si≤2,000,000,000。\

介绍

这题很难,所以我就不多说了。QWQ ~

展示代码!!!

#include<bits/stdc++.h>
using namespace std;
int read(){
    char ch=getchar();
    int a=0,x=1;
    while(ch<'0'||ch>'9'){
        if(ch=='-') x=-x;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9'){
        a=(a<<3)+(a<<1)+(ch-'0');
        ch=getchar();
    }
    return a*x;
}
int n,m1,m2,minx,ggbound,m,s,q,t,flag,tot,ans,tots,totq;       
int S[10001];
int gcd(int a,int b){
    if(b==0) return a;
    else return gcd(b,a%b);
}
int main(){
    n=read();
    m1=read();
    m2=read();
    minx=1e9;
    if(m1==1){cout<<0;return 0;}
    for(int i=1;i<=n;i++)S[i]=read();
    for(int i=1;i<=n;i++){
        tot=0;
        m=m1;                        
        s=S[i];                        
        flag=1;                
        t=0;                            
        while(m!=1){
            ggbound=gcd(m,s);         
            if(ggbound==1){flag=0;break;}  
            m/=ggbound;                    
            q=s/ggbound;                   
            s=ggbound;                    
            t++;                      
        } 
        if(flag){
            int gc=gcd(q,s);    
            if(gc!=1&&gc!=s){
                totq=0;tots=0;    
                while(q%gc==0){
                    totq++;       
                    q/=gc;
                }
                while(s%gc==0){
                    tots++;        
                    s/=gc;
                }
                if((t*m2*tots+totq*(t-1)*m2)%(tots+totq)==0)ans=(t*m2*tots+totq*(t-1)*m2)/(tots+totq);   
                else ans=(t*m2*tots+totq*(t-1)*m2)/(tots+totq)+1;
                minx=min(minx,ans);
            }
            else{
                while(q%s==0){
                    tot++;       
                    q/=s;           
                }
                if((t*m2+tot*(t-1)*m2)%(tot+1)==0)ans=(t*m2+tot*(t-1)*m2)/(tot+1);  
                else ans=(t*m2+tot*(t-1)*m2)/(tot+1)+1;
                minx=min(minx,ans);      
            }
        }
    }
    if(minx==1e9)cout<<-1;      
    else cout<<minx;
    return 0;
} 

QWQ~做题不易,给个关注多点爱!!!

  • 4
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值