[BZOJ2082][Poi2010][质因数分解][乱搞]Divine divisor

题意


找到最大k,使得若m为n的因数,则m^k也为n的因数,并求出有多少个m满足条件


BZOJ300题留念(果然还是不够)

在status里随手点开的题,因为要求最大的k,那么对于满足条件的n,不可能存在平方因子。
比如n有一个因数是p^2,因为n^k|m,即p^2k|m,则2k为更优的解。

那么只要把这个数质因数分解,答案一就是最大的次数。
令x为次数最大的质数的数量,2^x-1就是答案二。

刚开始暴力上rho…结果没有想到要打高精度,搜了发题解,听说貌似rho会被卡…..

简单讲一下网上的做法
把10^6以下的质数筛出来,把这些数中10^6以下的质因数都除去,那么剩下的数有三种情况,1.是素数 2.是两个不同素数的乘积 3.是素数的平方

1 3可以判定出来,对于2,因为只需要知道次数,不需要知道具体因数,两两数取gcd,就可以分解出来

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

using namespace std;

typedef long long ll;

int n;
int vis[610];
ll Ans1,Ans2;
ll p[1000010],A[610];
map app;

ll mul(ll x,ll y,ll mod){
  if(x0;  
  while(y){  
    if(y&1) if((r+=x)>=mod) r-=mod;
    if((x+=x)>=mod)x-=mod;
    y>>=1;
  }
  return r;
}

ll pow(ll x,ll y,ll mod){  
  ll r=1;
  while(y){  
    if(y&1) r=mul(r,x,mod);  
    x=mul(x,x,mod);  
    y>>=1;  
  }  
  return r;
}  

bool check(ll x,ll y,ll mod){  
  ll k=rand()%(mod-2)+2;  
  k=pow(k,x,mod);  
  if(k==1||k==mod-1) return 1;  
  for(ll i=1;i<=y;i++)
    if((k=mul(k,k,mod))==mod-1) return 1;
  return 0;  
}

bool judge(ll x){
  if(x<2) return 0;  
  if(!(x&1)) return x==2;  
  ll a=x-1,b=0;  
  while(!(a&1)) a>>=1,b++;  
  for(int c=1;c<=10;c++)
    if(!check(a,b,x))return 0;  
  return 1;  
}

struct Int{
  int a[1010],sz;
  int &operator [](int x){return a[x];}
  Int(){sz=0;memset(a,0,sizeof(a));}
  Int(ll x){sz=0;while(x)a[++sz]=x%10,x/=10;}
  friend Int operator *(Int a,Int b){
    Int c;c.sz=a.sz+b.sz-1;
    for(int i=1;i<=a.sz;i++)
      for(int j=1;j<=b.sz;j++)
    c[i+j-1]+=a[i]*b[j];
    for(int i=1;i<=c.sz;i++)
      if(c[i]>=10){
    c[i+1]+=c[i]/10; c[i]%=10;
    if(i==c.sz) c.sz++;
      }
    return c;
  }
  friend Int operator +(Int a,Int b){
    Int c;c.sz=max(a.sz,b.sz);
    for(int i=1;i<=c.sz;i++) c[i]=a[i]+b[i];
    for(int i=1;i<=c.sz;i++)
      if(c[i]>=10){
    c[i+1]+=c[i]/10; c[i]%=10;
    if(i==c.sz) c.sz++;
      }
    return c;
  }
  friend Int operator -(Int a,int b){
    a[1]-=b;
    for(int i=1;i<=a.sz;i++)
      if(a[i]<0){
    a[i+1]--; a[i]+=10;
    if(i==a.sz-1) a.sz--;
      }
    return a;
  }
  inline void print(){
    for(int i=sz;i;i--) putchar(a[i]+48);
    putchar('\n');
  }
};

inline Int _pow(ll y){
  Int r=1,x=2;
  while(y){
    if(y&1) r=r*x;
    x=x*x;
    y>>=1;
  }
  return r;
}

inline char nc(){
  return getchar();
  static char buf[100000],*p1=buf,*p2=buf;
  if(p1==p2){p2=(p1=buf)+fread(buf,1,100000,stdin); if(p1==p2)return EOF;}
  return *p1++;
}

inline void reaD(int &x){
  char c=nc();x=0;
  for(;c>57||c<48;c=nc());for(;c>=48&&c<=57;x=x*10+c-48,c=nc());
}

inline void reaD(ll &x){
  char c=nc();x=0;
  for(;c>57||c<48;c=nc());for(;c>=48&&c<=57;x=x*10+c-48,c=nc());
}

inline void pre(){
  for(int i=2;i<=1000000;i++){
    if(!p[i]) p[++p[0]]=i;
    for(int j=1;j<=p[0]&&1ll*p[j]*i<=1000000;j++)
      if(p[p[j]*i]=1,i%p[j]==0) break;
  }
}

ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}

inline void add(ll x,int y){
  if(x==1) return;
  ll k=(app[x]+=y);
  if(k>Ans1) Ans1=k,Ans2=1;
  else if(k==Ans1) Ans2++;
}

int main(){
  pre();
  reaD(n); ll x;
  for(int i=1;i<=n;i++){
    reaD(A[i]);
    for(int j=1;j<=p[0];j++)
      if(A[i]%p[j]==0){
    while(A[i]%p[j]==0){
      A[i]/=p[j];
      add(p[j],1);
    }
      }
    if(A[i]>1){
      ll k=(int)sqrt(A[i]);
      if(k*k==A[i]){
    add(k,2);
    vis[i]=1;
      }
      else{
    if(judge(A[i])){
      add(A[i],1);
      vis[i]=1;
    }
      }
    }
    else vis[i]=1;
  }
  for(int i=1;i<=n;i++)
    if(A[i]>1)
      for(int j=i+1;j<=n;j++)
    if(A[j]>1&&A[i]!=A[j]){
      ll k=gcd(A[i],A[j]);
      if(k==1) continue;
      if(!vis[i]) add(k,1),add(A[i]/k,1),vis[i]=1;
      if(!vis[j]) add(k,1),add(A[j]/k,1),vis[j]=1;
    }
  for(int i=1;i<=n;i++)
    if(!vis[i]) add(A[i]<<1,1),add(A[i]<<1|1,1);
  printf("%lld\n",Ans1);
  (_pow(Ans2)-1).print();
  return 0;
}

你可能感兴趣的:(乱搞,数学)