题意
找到最大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;
}