UVa294 Divisors
在一段区间[l,r]内,找出因数最多的数的个数以及其因数个数。
用唯一分解定理将一个数分解成质因数的乘积,例如 2^p1*3^p2*5^p3*7^p4*.... 从这些质因数中任选出一些数相乘,都可以组成原数的因数,总方案数为(p1+1)*(p2+1)*(p3+1)*... 注:+1是因为可以不选,全部不选的话得到数字1,也是原数的因数。
r<=1000000000,对其开根号得到31622,也就是说不会存在两个以上大于31622的质因数。素数筛算出1~3w+的质数。接下来用唯一分解定理算出区间内每个数的因数个数←暴力扫描即可。(0 ≤ L − R ≤ 10000)10000*30000次计算(实际到不了这么多),并不会炸。
1 /*by SilverN*/ 2 #include<iostream> 3 #include<algorithm> 4 #include<cstring> 5 #include<cstdio> 6 #include<cmath> 7 #define LL long long 8 using namespace std; 9 const int mxn=48000; 10 int pri[mxn],cnt=0; 11 bool vis[mxn]; 12 int num[mxn]; 13 void Pri(){//素数筛 14 cnt=0;int i,j; 15 for(i=2;i<mxn;i++){ 16 if(!vis[i])pri[++cnt]=i; 17 for(j=1;j<=cnt && i*pri[j]<mxn;j++){ 18 vis[i*pri[j]]=1; 19 if(i%pri[j]==0)break; 20 } 21 } 22 return; 23 } 24 int dvi(int a){//计算因数个数 25 int res=1; 26 int i,j; 27 int time=0; 28 for(i=1;i<=cnt && a>1;i++){ 29 time=0; 30 while(a%pri[i]==0){ 31 time++; 32 a/=pri[i]; 33 } 34 res*=(time+1); 35 } 36 if(a>1)res*=2; 37 return res; 38 } 39 int l,r; 40 int main(){ 41 Pri(); 42 int i,j; 43 int T; 44 scanf("%d",&T); 45 while(T--){ 46 scanf("%d%d",&l,&r); 47 int pos=l; 48 int mx=dvi(l);int tmp; 49 for(i=l+1;i<=r;i++){ 50 tmp=dvi(i); 51 if(tmp>mx){ 52 mx=tmp; 53 pos=i; 54 } 55 } 56 printf("Between %d and %d, %d has a maximum of %d divisors.\n",l,r,pos,mx); 57 } 58 return 0; 59 }
本文为博主原创文章,转载请注明出处。