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

来源:互联网 发布:jsp如何连接sqlserver 编辑:程序博客网 时间:2024/05/09 13:12

题意


找到最大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 <cstdio>#include <iostream>#include <algorithm>#include <cmath>#include <string>#include <cstring>#include <ctime>#include <map>using namespace std;typedef long long ll;int n;int vis[610];ll Ans1,Ans2;ll p[1000010],A[610];map<ll,ll> app;ll mul(ll x,ll y,ll mod){  if(x<y) swap(x,y);  ll r=0;    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;}
0 0