过剩数

11560 过剩数

时间限制:2000MS  内存限制:65535K

题型: 编程题   语言: 无限制

Description

对于一个正整数n,设S为n所有不同因子的和,如果有S-2*n>0则说n为过剩数,

现给两个正整数a和b(1<=a<=b<=100000),计算并输出a与b之间(包括a与b)有多少个
过剩数。

输入格式

多cases,最多1000个测试项
每一行两个数a与b,以一个空格分隔
最后一行为两个0

输出格式

对应每一行按题目要求输出一个数,最后一行不用输出

输入样例

1 10
10 100
100 1000
0 0

输出样例

0
22
225
本来也想着一次判断1~100000的数是不是过剩数,然后多次使用,但对每个数都去判断是否是过剩数必然超时,一时没思路,索性去百度:

完全数过剩数的正整数(>1)倍都是过剩数。

如6为完全数,那么 6的倍数都是过剩数。

证明:若x为完全数或过剩数,它的因子之和(除去自身)不小于x,对于nx,x所有因子的n倍都是nx的因子,其和不小于nx,除此之外,nx还有别的因子(如1),所以nx必然是过剩数。

根据上面这条定理效率便会提高很多

下面是代码:

#include <iostream>
#include <cmath>
using namespace std;
typedef long long ll;
const int maxn=100010;
ll a,b,m;

int g[maxn]={0,0,0},s[maxn]={0,0,};
//用数组g[]来标识是否是过剩数,s[n]统计小于等于n的过剩数个数
int is_abundant(ll x)//判断是否是过剩数
{
    int i;
    double temp=sqrt(x);

    ll sum=0;
    if(temp==(int)temp)
       sum+=(int)temp;

    for(i=1;i<temp;i++)
       if(x%i==0)
          sum+=i+x/i;

    if(sum>2*x)
       return 1;
    else
       return 0;
}

int main()
{
    int i,j,num=0;

    for(i=12;i<maxn;i++)
    {
        if(g[i]==1)
            s[i]=++num;
        else if( is_abundant(i) )
        {
            g[i] = 1;
            s[i] = ++num;
            for( j =i + i; j < maxn ; j +=i )  g[j] = 1;
        }
        else
            s [i] = num;
    }

    while( cin>>a>>b && (a||b) )
    {
        if( g[a] )
           cout<<s[b]-s[a]+1<<endl;
        else
           cout<<s[b]-s[a]<<endl;
    }
    return 0;
}
posted @ 2014-01-29 20:37  ForeverEnjoy  阅读(742)  评论(0编辑  收藏  举报