noip2009普及 细胞问题

noip2009普及 细胞问题_第1张图片

简单数论。真的很简单啦!非常显而易见: 这个细胞 i 在 t s后要均分,则必须是 m1^m2的倍数。怎么判断呢? m1^m2 的质因子种类和 m1 是一样的,指数则都是 m2 倍。细胞分裂只能增加 si 自身原有质因子的指数而不能得到新的质因子,在这个约束下,我们发现: si 必须包括 m1 的每种质因子——至少一个。一旦有不包含,即不合法。那么怎么求 t 呢?设对于 m1 的某个质因子 pi,m1 中有 ci 个, m1^m2 中有 ci^m2 个,si中有 ci’ 个,每次分裂 ci’ = ci’+ci’ (指数运算),这个质因子将在 ci*m2 / ci’ (向上取整) s 后满足条件,根据短板效应,这个细胞 i 满足均分条件所需的时间为 每一个质因子满足条件时的 ti 的最大值。

我其实不太想敲数论的博客啊,符号太多了好难打。T T

#include
using namespace std;

int n;
int s;
int m1_,m2_;

int cnt;
struct node
{
    int v,k;
}pri_[10000];

int ans;

inline void read(int &x)
{
    x=0;int f=1;char s=getchar();
    for(;s<'0'||s>'9';s=getchar()) if(s=='-') f=-1;
    for(;s>='0'&&s<='9';s=getchar()) x=(x<<3)+(x<<1)+s-48;
}

void divide_()
{
    memset(pri_,0,sizeof(pri_));
    cnt=0;
    for(int i=2;i*i<=m1_;++i)
        if(m1_%i==0)
        {
            pri_[++cnt].v=i;pri_[cnt].k=0;
            while(!(m1_%i)) m1_/=i,++pri_[cnt].k;
        }
    if(m1_!=1) pri_[++cnt].v=m1_,pri_[cnt].k=1;
    for(int i=1;i<=cnt;++i) pri_[i].k*=m2_;
}

int match_()
{
    int ans=0;
    for(int i=1;i<=cnt;++i)
        if(s%pri_[i].v) return 1e8;
        else{
            int k=0;
            while(!(s%pri_[i].v)) s/=pri_[i].v,++k;
            if(pri_[i].k%k) ans=max(ans,pri_[i].k/k+1);
            else ans=max(ans,pri_[i].k/k);//向上取整的很low的写法。
        }
    return ans;
}

void work_()
{
    read(n);
    read(m1_);read(m2_);
    divide_();//拆分质因子。
    ans=1e7;
    for(int i=1;i<=n;++i)
    {
        read(s);
        ans=min(ans,match_());
    }
    if(ans==1e7) printf("-1");
    else printf("%d",ans);
}

int main()
{
    work_();
    return 0;
}

你可能感兴趣的:(质数-约数。)