【BZOJ2082】【POI2010】Divine divisor 假的pollard-rho
题目大意:给你m个数ai,定义n=Πmi=1ai。将n分解质因数为Πpkii,pi是质数。请输出2max(ki)−1,以及存在多少个ki,满足ki=max(ki)。
数据范围:m≤600,ai≤1018。
这题有一种很显然的做法,采用pollard−rho对每个ai分解质因数,然后统计每种质因子出现的次数,最后取个max然后再统计下直接输出。
然而这题卡pollard−rho(比如来个9982443532),会TLE。
所以要采用一个比较高明的做法。
我们先用线性筛筛出[1,106]内的质数。
先用这些质数除以每一个ai,并统计这些质数出现的次数。
处理后的ai存在以下几种情况:
1,是数字1,无需处理。
2,是一个>106的质数,我们可以用Miller−Rabin来判断,处理很简单。
3,是一个>106的质数的平方,我们可以先对ai开跟,处理很简单。
4,是多个(其实只能是2个)>106的质数的乘积。
对于第4种情况,我们枚举两个不为1的ai和aj,求它们的最大公约数。
若它们的最大公约数不为1,那么我们就成功地把ai和aj给分解了。
没想到吧!!!!!!
然后就没有然后了
特别注意,此题的答案可能会很大,需要用高精度计算。
1 #include<bits/stdc++.h> 2 #define L long long 3 #define M 1000005 4 #define R(x) (1+rand()%(x-1)) 5 #define N 3000 6 using namespace std; 7 struct bign{ 8 int a[N+1]; 9 bign(){memset(a,0,sizeof(a));} 10 friend bign operator *(bign a,int b){ 11 int s,g=0; 12 for(int i=N;~i;i--){ 13 s=a.a[i]*b+g; 14 a.a[i]=s%10; g=s/10; 15 } 16 return a; 17 } 18 void minus(){ 19 int s,g=1; 20 for(int i=N;~i;i--){ 21 a[i]-=g; 22 if(a[i]<0){a[i]+=10; g=1;} 23 else return; 24 } 25 } 26 void out(){ 27 int i=0; 28 while(i<N&&a[i]==0) i++; 29 while(i<=N) printf("%d",a[i]),i++; 30 } 31 }a; 32 33 L mul(__int128 x,__int128 y,__int128 MOD){ 34 __int128 ans; 35 ans=x*y%MOD; 36 return ans; 37 } 38 L pow_mod(L x,L k,L MOD){ 39 L ans=1; 40 while(k){ 41 if(k&1) ans=mul(ans,x,MOD); 42 x=mul(x,x,MOD); k>>=1; 43 } 44 return ans; 45 } 46 map<L,int> mp; 47 bool checkprime(L x){ 48 if(x==2) return 1; if(x<2||x%2==0) return 0; 49 int times=20; 50 while(times--){ 51 L base=R(x-1); 52 if(pow_mod(base,x-1,x)!=1) return 0; 53 } 54 return 1; 55 } 56 57 int pri[M]={0},b[M]={0},use=0,is[M]={0}; 58 void pre(){ 59 for(int i=2;i<M;i++){ 60 if(!b[i]) pri[++use]=i; 61 for(int j=1;j<=use&&i*pri[j]<M;j++){ 62 b[i*pri[j]]=1; 63 if(i%pri[j]==0) break; 64 } 65 } 66 } 67 L num[M]={0},sum=0; 68 void chu(L &x){ 69 for(int i=1;i<=use;i++) 70 while(x%pri[i]==0) x/=pri[i],mp[pri[i]]++; 71 } 72 73 int main(){ 74 pre(); 75 int n; scanf("%d",&n); 76 for(int i=1;i<=n;i++){ 77 cin>>num[i];chu(num[i]); 78 if(num[i]==1){is[i]=3; continue;} 79 if(checkprime(num[i])) {is[i]=1;mp[num[i]]++;} 80 L hh=sqrt(((long double)num[i])); 81 if(hh*hh==num[i]) {mp[hh]+=2; is[i]=2;} 82 } 83 for(int i=1;i<=n;i++) if(is[i]!=2) 84 for(int j=i+1;j<=n;j++)if(is[j]!=2){ 85 if(num[i]==num[j]) continue; 86 L gcd=__gcd(num[i],num[j]); 87 if(gcd==1) continue; 88 if(is[i]==0) {mp[gcd]++; mp[num[i]/gcd]++; is[i]=4;} 89 if(is[j]==0) {mp[gcd]++; mp[num[j]/gcd]++; is[j]=4;} 90 } 91 for(int i=1;i<=n;i++) if(is[i]==0){ 92 mp[num[i]]++; 93 mp[-num[i]]++; 94 } 95 map<L,int>::iterator it; 96 int maxn=0,cnt=0; 97 for(it=mp.begin();it!=mp.end();it++) 98 maxn=max(maxn,it->second); 99 printf("%d\n",maxn); 100 for(it=mp.begin();it!=mp.end();it++) 101 if(it->second==maxn) cnt++; 102 a.a[N]=1; 103 while(cnt--) a=a*2; 104 a.minus(); 105 a.out(); 106 }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!