P1069 细胞分裂

P1069 细胞分裂

题解

 你看这道题的数据,很大,显然这是一道数学题

那么我们可以用分解质因数做

 

这道题也就相当于这样的问题

  ak = m1m2 

求解最小的 k 值

 

可以把两边进行质因数分解

如果方程有解的话,a 中一定包含 m1的所有质因子,a的质因子可以比 m

 

所以我们先把 m1 分解质因数,存到结构体 p 里,记录质因子的个数,质因子是什么,以及其指数

来一个新细胞 x 就分解一下这个细胞的质因数

然后枚举 m1 的所有质因子,一旦新细胞 x 没有 m1 的某个质因子,就退出,寻找下一个新细胞

对于 m1 和 x 的公共质因子,他们的指数不一定相同,最后的分裂次数和最大的指数差有关,因为 x 一定是要包含 m1 的,所以找到这个最大的指数差就好了

 

注意特盘:

如果 m1 是1的话,不用等待,直接就可以开始试验

 

 

代码

#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>

using namespace std;

int m1,m2,n;

struct node
{
    int cnt,zhi[50005],ci[50005]; 
    //cnt质因子的总个数,zhi[]存质因子,ci[]存质因子的次数 
}p,q;
//p存储m1,q存储细胞 

void fenjie(int x,node &p)    //分解质因数,把 x 分解到 p 里 
{
    p.cnt =0;
    for(int i=2;i*i<=x;i++)
    {
        if(x%i==0)
        {
            p.zhi[++p.cnt ]=i;
            p.ci [p.cnt ]=0;
            do
            {
                x/=i;
                p.ci [p.cnt ]++;
            }while(x%i==0);
        }
    }
    if(x>1)
    {
        p.zhi [++p.cnt ]=x;
        p.ci [p.cnt ]=1; 
    }
    
}

int main()
{

    scanf("%d",&n);
    scanf("%d%d",&m1,&m2);
    
    if(m1==1) { printf("0");   return 0; } 
    //特判 
    
    fenjie(m1,p);
    
    int ans=-1,x;  //x -> 新来的细胞 ,ans初始化-1
    
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&x);
        fenjie(x,q);
        
        int maxn=0,nxt=1;
        //maxn -> 该细胞的分裂次数 ; nxt -> x的质因子下标 
        
        int flag=0;  //默认无解 
        
        for(int j=1;j<=p.cnt ;j++)  //枚举m1的每个质因子 
        {
            while(q.zhi [nxt]<p.zhi [j]&&nxt<=q.cnt ) nxt++;
            //寻找x中,m1的质因子 
            
            if(q.zhi [nxt]>p.zhi [j]||nxt>q.cnt ) break;
            //如果找不到就直接退出 
            
            int f=p.ci [j]*m2/q.ci [nxt];
            if((p.ci [j]*m2)%(q.ci [nxt])) f++;
            //f记录细胞的分裂次数,如果除不尽的话就向上取整一下 
            
            if(maxn<f) maxn=f;
            //maxn记录的是对于当前这个细胞的分裂次数
            //求质因子指数的最大值,因为x要包含m1的每一个质因子 
            
            if(j==p.cnt ) flag=1;
            else flag=0;
            //标记找到了答案,记为1
            //如果找不到答案,前面会break掉 
        }
        
        if(flag&&(ans==-1||ans>maxn)) ans=maxn;
        //如果(有答案 &&(答案是第一次找到 || 原来答案比现在找到的大) )
        //更新答案为一个最小值 
    }
    
    printf("%d\n",ans);
    
    return 0;
}

 

 

 

~Thanks~

~神仙 ych QWQ~

posted @ 2019-06-19 08:34  晔子  阅读(438)  评论(0编辑  收藏  举报