uva294 Divisors

137 篇文章 0 订阅

Description Download as PDF

Mathematicians love all sorts of odd properties of numbers. For
instance, they consider 945 to be an interesting number, since it is
the first odd number for which the sum of its divisors is larger than
the number itself.

To help them search for interesting numbers, you are to write a
program that scans a range of numbers and determines the number that
has the largest number of divisors in the range. Unfortunately, the
size of the numbers, and the size of the range is such that a too
simple-minded approach may take too much time to run. So make sure
that your algorithm is clever enough to cope with the largest possible
range in just a few seconds.

Input Specification

The first line of input specifies the number N of ranges, and each of
the N following lines contains a range, consisting of a lower bound L
and an upper bound U, where L and U are included in the range. L and U
are chosen such that tex2html_wrap_inline42 and tex2html_wrap_inline44
.

Output Specification

For each range, find the number P which has the largest number of
divisors (if several numbers tie for first place, select the lowest),
and the number of positive divisors D of P (where P is included as a
divisor). Print the text ‘Between L and H, P has a maximum of D
divisors.’, where L, H, P, and D are the numbers as defined above.

因为l..r不大,所以可以暴力枚举每个数统计因数个数。
先打出来素数表,然后用每个素数试除,记指数分别为p1,p2,…,pn,则因子个数为(p1+1) * (p2+1) * … * (pn+1)。
时间复杂度((r-l) * sqrt(r)/log(sqrt(l)))。

#include<cstdio>
#include<cstring>
int prm[40010],tot;
bool have[40010];
int cnt(int x)
{
    int ans=1,p,q;
    for (int i=1;i<=tot&&x>1;i++)
      if (x%prm[i]==0)
      {
        p=0;
        while (x%prm[i]==0)
        {
            p++;
            x/=prm[i];
        }
        ans*=p+1;
      }
    if (x>1) ans*=2;
    return ans;
}
int main()
{
    int i,j,k,m,n,p,q,x,y,z,T,l,r;
    for (i=2;i<=40000;i++)
    {
        if (!have[i]) prm[++tot]=i;
        for (j=1;j<=tot&&i*prm[j]<=40000;j++)
        {
            have[i*prm[j]]=1;
            if (i%prm[j]==0) break;
        }
    }
    scanf("%d",&T);
    while (T--)
    {
        scanf("%d%d",&l,&r);
        p=l;
        q=cnt(l);
        for (i=l+1;i<=r;i++)
        {
            x=cnt(i);
            if (x>q)
            {
                q=x;
                p=i;
            }
        }
        printf("Between %d and %d, %d has a maximum of %d divisors.\n",l,r,p,q);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值