码迷,mamicode.com
首页 > 其他好文 > 详细

HDU 5211 筛法求约数

时间:2015-04-27 00:00:02      阅读:256      评论:0      收藏:0      [点我收藏+]

标签:

给出n个数a1,a2...an,定义函数 f[i]=j,(i<j),表示aj mod ai=0 的最小j,其中j大于i,如果不存在这样的数,则f[i]=0

求n个数所有f[]值的和

 

先用筛法o(nlogn)求出每个数的约数

然后每读入一个数x,先找出所有的约数,再看看之前有没有出现过这些约数。

这个回看的过程可以用一个数组维护。

维护watch[],watch[aj]=j 表示aj还没有找到函数值,如果aj是x的约数,那么说明aj的函数值为x的位置。

 

#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<set>
#include<map>
#include<stack>
#include<vector>
#include<queue>
#include<string>
#include<sstream>
#define eps 1e-9
#define ALL(x) x.begin(),x.end()
#define INS(x) inserter(x,x.begin())
#define FOR(i,j,k) for(int i=j;i<=k;i++)
#define MAXN 1005
#define MAXM 40005
#define INF 0x3fffffff
#define PB push_back
#define MP make_pair
#define X first
#define Y second
#define lc (k<<1)
#define rc ((k<<1)1)
using namespace std;
typedef long long LL;
int i,j,k,n,m,x,y,T,ans[10005],big,cas,num,len;
bool flag;
int sum,wat[10005];

vector <int> fac[10005]; 
void GetFact(int size)
{
    for (int i=1;i<=size;i++)
    {
        for (int j=i;j<=size;j+=i) 
        {
            fac[j].push_back(i);
        }    
    }
}

int main()
{
    GetFact(10000);
    while (~scanf("%d",&n))
    {
        memset(wat,0,sizeof(wat));
        memset(ans,0,sizeof(ans));
        for (i=1;i<=n;i++)
        {
            scanf("%d",&x);
            for (j=0;j<fac[x].size();j++)
            {
                int u=fac[x][j];
                if (wat[u])
                {
                    k=wat[u];
                    ans[k]=i;
                    wat[u]=0;
                }
            }
            wat[x]=i;
        }
        sum=0;
        for (i=1;i<=n;i++)
        {
            sum+=ans[i];
        }
        printf("%d\n",sum);
    }

    return 0;
}

 

HDU 5211 筛法求约数

标签:

原文地址:http://www.cnblogs.com/zhyfzy/p/4458618.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!