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 数学杂题

时间: 2024-10-12 18:33:46

hdu 4961 数学杂题的相关文章

hdu 4974 数学杂题/证明

题意模型:n个正数,每次可以做下面俩种操作之一: 1:取一个数减一. 2:取俩个数各减一. 都必需保证每次操作的数>0. 求使得所有数字为0的最少操作次数. 都说是简单题,网上还有不少错误解法(排序后扫一遍,每次取最大的俩个数减到0: 2 2 2 这样是4次,正解3次). 应该是每次取最大的俩个数,各减1. 若maxi>sum/2,则ans=max,每次操作都用那个max,和其他一个数,最后max没人找了,自己减. 若maxi<sum/2,则ans=(sum+1)/2.每次操作找俩个当前

hdu 4432 数学杂题

http://acm.hdu.edu.cn/showproblem.php?pid=4432 6分钟写的代码,一上午去调试,, 哎,一则题目没看懂就去写了,二则,哎,,恶心了,在坚持几天然后ACM退役,想当初一直想着regional拿奖,然后在保研的时候有个更漂亮的简历,卧槽,但是,其实喜欢的是静下心,把一块知识好好弄懂,看着自己一点点由不会到会,由不熟到熟练,而且在这个过程中总结一些思考问题的方法,能把这种思维应用于其他 但是----唉,急功近利式地学,老想着快,一没思路就去看题解,然后平均每

hdu 3641 数论 二分求符合条件的最小值数学杂题

http://acm.hdu.edu.cn/showproblem.php?pid=3641 学到: 1.二分求符合条件的最小值 /*==================================================== 二分查找符合条件的最小值 ======================================================*/ ll solve() { __int64 low = 0, high = INF, mid ; while(low <=

HDU 4961 基础维护题

先附上题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4961 题意是给你一串数, 对于其中一个位置的数, 找出这两个数, 第一个数是这个数前面距离此数最近且为这个数的倍数的数, 第二个数是找出后面距离此数最近且是这个数的倍数的表, 对于每个位置的数, 将这个位置的两个数之积求出来再求和即可, 代码如下: #include <cstdio> #include <algorithm> #include <cstring> #i

hdu4972 数学杂题

题意:有俩个队进行n场比赛,每场只记录下分差的绝对值(不知道哪一方),求最后可能比分. 思考了半天,还分类讨论..结果也想到只有 1->2.2->1的情况有俩种可能...哎还是跪,这题坑点交多,自己弱爆.. 官方正解:既然已经知道差值,那么只有知道双方最终得分之和就知道比分了!(x-y已知,当然要用x+y去确定!问题转化能力!)问题转化了!每次1->2/2->1有总分增加1/3的俩种可能,设有cnt个,则有cnt+1个和(0个1,1个1...cnt个1),当最后比分一样(x-y=0

1005:Number Sequence(hdu,数学规律题)

Problem Description A number sequence is defined as follows: f(1) = 1, f(2) = 1, f(n) = (A * f(n - 1) + B * f(n - 2)) mod 7. Given A, B, and n, you are to calculate the value of f(n). Input The input consists of multiple test cases. Each test case co

zoj 3629 数学杂题

//#pragma comment(linker, "/STACK:102400000,102400000") #include <cstdio> #include <cstring> #include <algorithm> #include <string> #include <iostream> #include <iomanip> #include <cmath> #include <ma

BZOJ3629-聪明的燕姿【数学杂题】

T浪h改姆9少FVT优乐Phttp://www.docin.com/vwhd00606 AM0瓤XN7Ukahttp://weibo.com/u/6367436044 蹈4s釉畏耐E帜2先http://shufang.docin.com/sina_6372939737 惨涟谴涸魄4wm械狡4禄whttp://tushu.docin.com/sina_6359754391 43X86p至靡06第h貉2http://www.docin.com/jpvfe032 7rfa03噬2l障http://hu

HDU 4961(杭电多校#9 1002题)Boring Sum(瞎搞)

题目地址:HDU 4961 看来这题的测试数据是随机的.不然出了极限数据还真过不了...这题我的方法是建一个哈希结构体,记录两个变量,分别是num位置,然后是f,f==0表示这个数没出现过,f==1表示这个数出现过.然后分别从前面和后面扫一遍.每次扫的时候,对每一个出现的数都进行标记.然后对当前的数枚举该数的倍数,全部枚举完,取位置num最大的.然后找完之后,对哈希结构体进行更新.如果前面曾经出现过的话,就直接换掉,因为后面的数总比前面的更优.最后扫完两遍之后两个数组就能求出来了.计算就行了.