Poi2010 Divine Divisor

来源:互联网 发布:windows api 窗口置顶 编辑:程序博客网 时间:2024/04/27 20:11

Solution:

首先我们想到吧所有的数质因子分解,所得到的每个质因子的个数的和的最大值就是要求的k,而我们设这个最大值出现的次数为m,则我们可以知道,任意个这样的质因子的乘积都是可行的一种解,所以第二个答案就是2^m,注意到这个值可能会很大,所以我们要用高精乘法.

那么我们再观察一下现在这个数的范围->[1,1e18],根本无法去进行完全的因数分解,但是我们可以知道,如果这个范围内的数有三个或以上的因数,那么这个因数一定小于等于1e6,那么我们处理出1e6及以下的质数,就足以排除出所有有三个或以上的因子的数和小于等于1e12的数了.

那么剩下的数有三种可能,为表达方便,设它的两个因子为p,q.那么只有三种可能:

1.p=q.那么就可以知道这个数是一个完全平方数而且p和q都是素数,这个可以直接在开始时处理.

2.p!=q,p,q!=1.这个时候我们通过将这种数两两求gcd,就可以知道它们可能的因子,从而分解它们,而如果在其他数中没有发现它的因子,那么会有两种可能:(1)它的因子在之前算出的数中.(2)它的因子不在之折算出来的数中.

而我们后面算出的那些因数都可以通过求gcd而得,所以这些数中不会有现在这个数的因子,所以我们要在原来的因子中来求这个数的因子.而如果没有的话,那么代表它的因子在之前根本没有出现过,所以我们先存下它,以后再去处理.

3.p=1,q!=1.这就代表它是一个大素数,判断方法为Miller Rabin(详情请点击此处.这时只要把这个数的次数加1就行了.

呃,最后剩下了之前的没有因数的数,对于这样的数,我们有了它的值以及它所出现的个数,而我们知道它的因子是在之前(之后)都不会出现的.所以我们可以随便给它赋一个偶数的值作为代替就行了(因为不需要输出方案(实际也输不出来)).

#include<cstdio>#include<cstring>#include<cmath>#include<cstdlib>#include<ctime>#include<iostream>#include<algorithm>#include<map>#include<set>#define M 1000005#define LL long long#define P 10000using namespace std;bool vis[M];int f[M],sz=0;struct BigInt{    int num[505],len;    BigInt(){        memset(num,0,sizeof(num));        len=0;    }    BigInt operator *(const BigInt &a)const{        BigInt re;        re.len=len+a.len-1;        for(int i=0;i<len;i++)            for(int j=0;j<a.len;j++){                int &res=re.num[i+j];                res+=num[i]*a.num[j];                if(res>=P){                    re.num[i+j+1]+=res/P;                    res%=P;                }            }        if(re.num[re.len]!=0)re.len++;        return re;    }    void Pr(){        printf("%d",num[len-1]);        for(int i=len-2;i>=0;i--)printf("%04d",num[i]);    }};void Init(){    for(int i=2;i<M;i++)        if(!vis[i]){            f[sz++]=i;            for(int j=i<<1;j<M;j+=i)vis[j]=true;        }}void Rd(LL &res){    res=0;    char p;    while(p=getchar(),!(p>='0'&&p<='9'));    do{        res=(res<<1)+(res<<3)+(p^48);    }while(p=getchar(),p>='0'&&p<='9');}LL a[M];LL gcd(LL a,LL b){    return b==0?a:gcd(b,a%b);}map<LL,int>cnt;map<LL,int>mp;int Mx=0,cn=0;int n;void doit(LL &x){    for(int i=0;i<sz&&1LL*f[i]*f[i]<=x;i++)        if(x%f[i]==0){            int c=0;            while(x%f[i]==0)c++,x/=f[i];            cnt[f[i]]+=c;        }    if(x<=1LL*(M-10)*(M-10)&&x!=1)cnt[x]++,x=1;}void Pow(int x){    BigInt ans,res;    ans.len=1,ans.num[0]=1;    res.len=1,res.num[0]=2;    while(x){        if(x&1)ans=ans*res;        res=res*res;        x>>=1;    }    ans.num[0]-=1;    ans.Pr();    puts("");}void Add(LL &x,LL y,LL Bas){    x+=y;    if(x>=Bas)x-=Bas;}LL Mul(LL a,LL b,LL Bas){    LL re=0;    if(a<b)swap(a,b);    LL res=a;    while(b){        if(b&1)Add(re,res,Bas);        Add(res,res,Bas);        b>>=1;    }    return re;}LL Hax(LL Mi,LL x,LL Bas){    LL re=1;    LL res=Mi;    while(x){        if(x&1)re=Mul(re,res,Bas);        x>>=1;        res=Mul(res,res,Bas);    }    return re;}bool check(LL ned,LL t,LL Bas){    LL p=1LL*rand()*rand()%(Bas-2)+2;    p=Hax(p,ned,Bas);    if(p==1||p==Bas-1)return false;    for(int i=1;i<=t;i++){        p=Mul(p,p,Bas);        if(p==Bas-1)return false;    }    return true;}bool judge(LL x){    if(x<=2)return true;    if(x%2==0)return false;    LL u=x-1;    int t=0;    while(!(u&1))u>>=1,t++;    for(int i=1;i<=10;i++)        if(check(u,t,x))return false;    return true;}set<LL>st,rst;int main(){    srand(time(NULL));    scanf("%d",&n);    Init();    int sz=0;    for(int i=1;i<=n;i++){        LL x;        Rd(x);        doit(x);        if(x==1)continue;        LL hal=sqrt(x)+0.1;        if(hal*hal==x){            cnt[hal]+=2;        }else {            if(judge(x))cnt[x]++;            else a[sz++]=x;        }    }    for(int i=0;i<sz;i++){        st.clear();        bool f=false;        for(int j=0;j<sz;j++){            if(i==j)continue;            LL GCD=gcd(a[i],a[j]);            if(GCD!=1&&GCD!=a[i])st.insert(GCD),st.insert(a[i]/GCD);            else if(GCD==a[i]&&a[j]!=a[i])f=true;        }        if(st.empty()&&!f){            if(mp.find(a[i])!=mp.end())mp[a[i]]++;            else {                f=false;                for(map<LL,int>::iterator it=cnt.begin();it!=cnt.end()&&(it->first)*(it->first)<=a[i];it++)                    if(a[i]%(it->first)==0){                        (it->second)++;                        cnt[a[i]/(it->first)]++;                        f=true;                        break;                    }                if(!f)mp[a[i]]++;            }        }else if(f)cnt[a[i]]++;        for(set<LL>::iterator it=st.begin();it!=st.end();it++)cnt[*it]++;    }    int k=58;    for(map<LL,int>::iterator it=mp.begin();it!=mp.end();it++)        cnt[k*2]+=(it->second),cnt[k*2+2]+=(it->second),k+=4;    for(map<LL,int>::iterator it=cnt.begin();it!=cnt.end();it++)        if(it->second>Mx)Mx=it->second,cn=1;        else if(it->second==Mx)cn++;    printf("%d\n",Mx);    Pow(cn);    puts("");    return 0;}
1 0
原创粉丝点击