zoukankan      html  css  js  c++  java
  • 求个最大值(技巧+二分转化)

    求个最大值

    时间限制: 1 Sec  内存限制: 128 MB
    提交: 267  解决: 52
    [提交][状态][讨论版]

    题目描述

    给出 n(1 <= n <= 200000)个数字 ai(1 <= ai <= 1000000),i 为数字的下标,按输入顺序从 1 开始编号
    一直到 n,求满足 ai >= aj 的最大的 ai % aj。 

    输入

    第一行一个数字 n,第二行 n 个整数。 

    输出

    题目要求的最大值。 

    样例输入

    2
    2 3
    

    样例输出

    1
    

    提示


    题解:

    排序去重之后,对1到 max{ai}中的每个数字x求出小于x的最大 ai,记为 b[x]。 对于每个 ai 枚举它的倍数即可,时间复杂度 O(max{ai} + nlogn) 。 

    这题比赛里已经想到思路了,就是不知道怎么去表示。。 思路很简单,设a, b , a > b -> a/b = k....r(r是余数),这样我们肯定希望a离着k*b越元越好。也就是我们枚举倍数的时候(比赛中写过枚举倍数,但是n*n的。。)我们希望b*k离着a越远越好,但是不能远过b的大小,这样就难处理了,但是可以转化成 (k+x)*b离着a越近越好,那枚举到每个数的倍数时候,对他有用的就只有一个离着这个数最近的a【i】了、、前缀处理下就好了。。记录1-maxn*2每个数比他小但是最大的a[i]就行。。


    这个问题中有几个点还是比较巧妙的!!!

    (1)求的是a[j]>a[i] 且a[j]%a[i]的最大值,如果把研究a[j]的话问题是不好解决的,需要转化一下,也就是上面的这个转化过程,用倍数来想

    (2)开始的时候我是感觉这样会超时的,因为开始的时候如果a[i]=2,这需要(200000*2)/2=200000的,然后每个数按照这种最坏的想,也就是200000*20000,这明显是会超时的,但是之后计算之后发现最大值是134565766,也就是说复杂度是1e7,不会超时的,其实这就是个调和级数计算方式(调和级数的值:n趋近与无穷后是:1/1+1/2+1/3...+1/n~ln(n+1) +r,r是欧拉常数,r=0.5772156649.),就是高数级数里面一个简单的概念好不好,都忘了。。还有这里其实就是放缩放错了,放缩方法分两种的好不好,张宇十八讲上好像看过敲打,趋近于无穷的是不能简单用最大的放缩的。。。

    (3)想要找到最接近a[j]的某个值,第一想法肯定是二分思想比较快,但是这里又是做了一个巧妙的思想,就是用了这个辅助数组,所以查找就直接是O(1)了,相当巧妙,学习了!!!


    #include <bits/stdc++.h>
    using namespace std;
    
    const int maxn = 1e6 + 10;
    int b[maxn], a[maxn];
    int main()
    {
        int n;
        while(~scanf("%d", &n))
        {
            memset(b, 0, sizeof(b));
            for(int i = 1; i <= n; i++)
                scanf("%d", &a[i]);
            sort(a+1, a+1+n);
            int index = a[1]+1;
            a[n+1] = maxn*2;
            for(int i = 2; i <= n+1; i++) ///记录比j小的最大的a[i]
                while(index <= a[i])
                    b[index++] = a[i-1];
            int ans = 0;
            for(int i = 1; i <= n; i++)
                for(int j = a[i]*2; j <= maxn*2; j += a[i])
                    ans = max(ans, b[j]%a[i]);
            printf("%d
    ", ans) ;
        }
        return 0;
    }
    


    还有网上有的说二分可以,按照上面复杂度计算是不可以的,并且竞赛之后发现已经回TL了!!!







  • 相关阅读:
    十一周
    第五次作业
    第十周
    测试作业
    2016.06.24-2016.06.30这周工作时间和内容
    2016.06.10-2016.06.16这周工作时间和内容
    2016.06.03-2016.06.09这周工作时间和内容
    2016.05.26-2016.06.02这周工作时间和内容
    2016.05.20-2016.05.26这周工作时间和内容
    分答
  • 原文地址:https://www.cnblogs.com/zswbky/p/8454152.html
Copyright © 2011-2022 走看看