hdu 4961 数学杂题

http://acm.hdu.edu.cn/showproblem.php?pid=4961

先贴个O(nsqrtn)求1-n所有数的所有约数的代码:

vector<int>divs[MAXN];

void caldivs()
{
     for(int i=1;i<MAXN;i++)
        for(int j=i;j<MAXN;j+=i)
            divs[j].push_back(i);
}

有了这个当时理下思路就可写了,但是重复数处理注意:

1、用一个数组vis[]  vis[i]=1表示i存在 或者pos[v]=j表示v在下标为j的位置  这种方法,虽然高效,但是如果出现重复的数,pos就只是更新到最近的一个数,而且vis只是记录了一个数,最好vis[i]++,如果删除一个数vis[i]--;

处理了重复数281ms AC

100000这个范围的数,即使多CASE,nsqrtn的算法还是可以一搞的

奇怪的是C++显示stack_overflow  G++ AC   可是我没有递归啊,难道vector

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <string>
#include <iostream>
#include <iomanip>
#include <cmath>
#include <map>
#include <set>
#include <queue>
using namespace std;

#define ls(rt) rt*2
#define rs(rt) rt*2+1
#define ll long long
#define ull unsigned long long
#define rep(i,s,e) for(int i=s;i<e;i++)
#define repe(i,s,e) for(int i=s;i<=e;i++)
#define CL(a,b) memset(a,b,sizeof(a))
#define IN(s) freopen(s,"r",stdin)
#define OUT(s) freopen(s,"w",stdout)
const ll ll_INF = ((ull)(-1))>>1;
const int MAXN = 1e5+10;
const int INF = MAXN*13;///
int vis[MAXN];
int a[MAXN],b[MAXN],c[MAXN];
int maxm[MAXN],minm[MAXN],f[MAXN],g[MAXN],maxpos[MAXN],minpos[MAXN];
vector<int>divs[MAXN];

void caldivs()
{
     for(int i=1;i<MAXN;i++)
        for(int j=i;j<MAXN;j+=i)
            divs[j].push_back(i);
}
int n;
ll ans;
int main()
{
    //IN("1002.txt");
    caldivs();
    while(~scanf("%d",&n) && n)
    {
        vector<int>pos[MAXN];
        CL(vis,0);
        for(int i=0;i<n;i++)
        {
            scanf("%d",&a[i]);
            vis[a[i]]++;
            pos[a[i]].push_back(i);
            maxm[i]=-INF;//
            minm[i]=INF;//
        }
        for(int i=0;i<n;i++)
            for(int j=0;j<divs[a[i]].size();j++)
            {
                int vv = divs[a[i]][j];
                if(vis[vv])
                {
                    for(int k=0;k<pos[vv].size();k++)
                    {
                        if(i<pos[vv][k])
                            maxm[pos[vv][k]]=max(maxm[pos[vv][k]],i);
                        if(i>pos[vv][k])
                            minm[pos[vv][k]]=min(minm[pos[vv][k]],i);
                    }
                }
            }

        /*for(int i=0;i<n;i++)
        {
            for(int j=0;j<divs[a[i]].size();j++)
            {
                if(vis[divs[a[i]][j]] && maxpos[a[i]]<pos[divs[a[i]][j]])
                {
                    maxm[divs[a[i]][j]]=max( maxm[divs[a[i]][j]],maxpos[a[i]] );
                }
                if(vis[divs[a[i]][j]] && minpos[a[i]]>pos[divs[a[i]][j]] )
                {
                    minm[divs[a[i]][j]]=min( minm[divs[a[i]][j]],minpos[a[i]] );
                }
                ////////////
                //printf("%d %d ma=%d mi=%d \n",divs[a[i]][j],a[i],maxm[9],minm[9]);
                /////////////
            }
        }*/
        ans=0;
        for(int i=0;i<n;i++)
        {
            if(maxm[i]==-INF)
            {
                f[i]=maxm[i]=i;//maxm相当于f
            }
            else
            {
                f[i]=maxm[i];
            }
            b[i]=a[f[i]];
            if(minm[i]==INF)
            {
                g[i]=minm[i]=i;//minm相当于g
            }
            else
            {
                g[i]=minm[i];
            }
            c[i]=a[g[i]];
            ans+=(long long)b[i]*c[i];
        }
                ////////////////
        /*for(int i=0;i<n;i++)
        {
            printf("###ma=%d mi=%d\n",f[i],g[i]);
        }*/
        //////////////////
        printf("%I64d\n",ans);
    }
    return 0;
}


你可能感兴趣的:(hdu 4961 数学杂题)