NYOJ-487月老的烦恼(1)类似于素数筛法一样的打表及一种筛法核心代码。。

月老的烦恼(1)

时间限制: 1000 ms  |  内存限制: 65535 KB
难度: 3
描述

月老最近遇到了一个很棘手的问题,就是“剩男”“剩女”急速增长,而自己这边又人手不足导致天天都得加班。现在需要你来帮助月老解决这个问题,牵红绳的规则很简单:每个男生都一个编号n(1<=n<=500000),编号n的因数之和就是要牵线的女生的编号。

如20的因子是:1,2,4,5,10;

 

输入
输入数据的第一行是一个数字T(1<=T<=500000),它表明测试数据的组数.然后是T组测试数据,每组测试数据只有一个数字N(1<=N<=500000).
输出
对于每组测试数据,请输出一个代表输入编号N男生的另一半的编号.
样例输入
3
2
10
12

样例输出

1
8
16


  先看数据范围,两层for循环肯定超时,我们首先想到的是打表,可是题目要求的是因子和,怎么筛选出因子呢,,

下面先来看看素数筛法:

          一种筛法核心代码:

    for(i=2; i<=1000000; i++)

    {

        if(a[i])

            for(j=2*i; j<=1000000; j+=i)

                a[j]=0;//以前还以为会超时,后来发现原来实际上省了好多步骤。。

    }//这个时间复杂度可能要比线性筛法更高,但线性筛法还没有掌握。。。


类似于素数打表,我们发现既然求因子和,那么何不将因子累加呢,从因子的角度出发;

   类似于筛法一样的打表:

    for(i=2; i<=250000; i++)

            for(j=2*i; j<=500000; j+=i)

                a[j]+=i;//是不是很神奇,,这也不会超时。

  

#include<bits/stdc++.h>
using namespace std;
const int N=500000+10;
int a[N];
int main()
{
    int t,n,i,j;
    memset(a,0,sizeof(a));
    for(i=2; i<=250000; i++)
            for(j=2*i; j<=500000; j+=i)
                a[j]+=i;//打表;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
       printf("%d\n",n==1?0:a[n]+1);
    }
    return 0;
}//比较简洁易懂; 



你可能感兴趣的:(NYOJ-487月老的烦恼(1)类似于素数筛法一样的打表及一种筛法核心代码。。)