最多约数问题

来源:互联网 发布:微信客服系统 知乎 编辑:程序博客网 时间:2024/06/11 06:25

问题描述:
正整数x的约数是能整除x的正整数。正整数x 的约数个数记为div(x)。例如,1,2,5,10 都是正整数10 的约数,且div(10)=4。设a 和b 是2 个正整数,a≤b,找出a和b之间约数个数最多的数x。
编程任务:
对于给定的2个正整数a≤b,编程计算a 和 b 之间约数个数最多的数。
数据输入:
输入数据由文件名为input.txt的文本文件提供。文件的第1 行有2 个正整数 a和 b。
结果输出:
程序运行结束时,找到a 和b之间约数个数最多的那个数及最多约数个数。

测试数据:【只给出最多约数个数, time limit: 1s】
[1, 36]                               9
[1000000, 2000000]           288
[999998999, 999999999]    1024
[1, 1000000000]                 1344
[999999999, 1000000000]   56
[100, 1000000000]              1344
---------------------------------------

方法一:啥都不管,直接遍历区间内每个数的约数个数,求最多。
#include<iostream>
#include<cmath>
using namespace std;
long counts(long num)
{
long i;
long cnt = 0; // count the prime
long up = sqrt(num);
for (i = 1; i <= up; i++)
{
if (num % i == 0)
{
if ((i == up) && (i*i == num)) cnt++;
else cnt += 2;
}
}
return cnt;
}

int main()
{
long low, up, maxnum, numb;
cin >> low >> up;
maxnum = 1;
numb = low;
for (long i = low; i <= up; i++)
{
long k = counts(i);
if (maxnum < k)
{
maxnum = k;
numb = i;
}
}
cout << maxnum << endl << numb << endl;
return 0;
}
这样的话,时间复杂度大概为 1^1/2 + 2^1/2 + ……+N^1/2,即
N<O(N)<N^2。
当测试数据大时程序严重超时。

----------------------------------------------------------------------------------------------------------

方法二:按照书上给的算法(Page6),设正整数x的质因子分解为
x=p1^N1 × p2^N2 ×……pi^Ni
则 div(x)=(N1+1)(N2+1)……(Ni+1)。
程序运行正确,效率也行,就是下面用红色标注的语句有些不明白,还请大侠们多指教……
Environment: MS VC6.0
#include<iostream>
using namespace std;

const long MAXP = 100000;
long prim[MAXP];
long max, numb, PCOUNT; //max存放最多约数个数,numb存放约数个数最多的数

void primes(); //用筛选法产生质数存于prim数组中
void search(long from, long tot, long num, long low, long up);

int main()
{
primes();
long l, u;
cin >> l >> u;
if ((l == 1) && (u == 1))
{
max = 1;
numb = 1;
}
else
{
max = 2;
numb = l;
search(1, 1, 1, l, u);
}
cout << max << endl << numb << endl;
return 0;
}


void primes() //执行完后: prim[]={2, 3, 5, 7, 11, 13……}
{
bool get[MAXP+1];
long i;
for (i = 2; i <= MAXP; i++)
get[i] = true;

for (i = 2; i <= MAXP; i++)
if (get[i])
{
long j = i + i;
while (j <= MAXP)
{
get[j] = false;
j += i;
}
}
long ii, j;
for (ii = 2, j = 0; ii <= MAXP; ii++)
if (get[ii]) prim[++j] = ii;
PCOUNT = j;
}

// 区间[low,up]上,tot为当前约数最多个数,num为约数个数最多的数,
//from表示现在是第几个质数。
void search(long from, long tot, long num, long low, long up)
{
if (num >= 1)
if ( (tot > max) || ((tot == max) && (num < numb)) )
{
max = tot;
numb = num;
}

if ((low == up) && (low > num))
search(from, tot*2, num*low, 1, 1);
  
for (long i = from; i <=PCOUNT; i++)
{
if (prim[i] > up) return;  
         else
{
long j = prim[i], x = low - 1, y = up, n = num, t = tot, m = 1;
while (true)
{
m++;
t += tot;
x /= j;
y /= j;
if (x == y) break;
n *= j;
search(i+1, t, n, x+1, y);
}
m = 1 << m;
           
   if (tot < max / m) return;
        }//end else
}//end for
}

原创粉丝点击