zoukankan      html  css  js  c++  java
  • 2018网易在线笔试题

    第一题

    解决思路:分类讨论
    当k==0的时候,有n*n对答案
    当k!=0的时候,设x%y=z,z>=k.分类讨论:当x<y的时候,当x>y的时候

    def simple(n, k):
        cnt = 0
        for i in range(1, n + 1):
            for j in range(1, n + 1):
                if i % j >= k:
                    cnt += 1
        return cnt
    
    
    def better(n, k):
        if k == 0:
            return n * n
        s = 0
        for i in range(k, n + 1):
            s += n - i
        for i in range(k + 1, n):
            group_count = n // i
            s += (group_count - 1) * (i - k)
            s += max(0, n % i - k + 1)
        return s
    
    
    def test():
        import random
        n = random.randint(3, 100)
        k = random.randint(0, n)
        return simple(n, k) == better(n, k)
    
    
    for _ in range(1000):
        ans = test()
        if not ans:
            exit(-1)
    
    

    第二题

    解决思路:如果暴力枚举,$2{30}$显然太大了.如果是$215$那该多好哇!那样我就只需要开辟一个大数组,从0,一直循环到$2^{15}-1$就可以了.
    此题的正确思路就是:分治,创建两个大数组a[65536],b[65536],分别表示前半部分物品选择情况和后半部分选择情况,a[i]表示决策i(用i的二进制表示是否选择某个物品)的体积总和.接下来,对于每一个a[i],寻找b中小于v-a[i]的决策.此步可以通过排序+二分搜索极好地优化.

    于是余有叹焉:

    这道题的分治真是令人大开眼界,仔细回忆一下,我们过去学过的一切分治算法,无一不是跟递归紧密联系起来的.似乎解决问题一旦分治就要以递归的方式分治到底.
    而实际上,这却是错觉.
    程序设计的目的在于在有限的时间和空间内实现某个目的,如果分治一次足以解决任务,那就够了.在这道题中,只能够分治一次,而无法做到多次分治.因为既然分治,必然涉及到合并分治结果.而多次分治就会造成合并困难.

    import java.io.FileInputStream;
    import java.io.FileNotFoundException;
    import java.util.Arrays;
    import java.util.Scanner;
    
    public class Main {
    static long[] build(int[] a, int beg, int end) {
        int n = end - beg;
        long ans[] = new long[1 << n];
        for (int i = 0; i < ans.length; i++) {
            long s = 0;
            for (int j = 0; j < n; j++) {
                if ((i & (1 << j)) != 0) {
                    s += a[beg + j];
                }
            }
            ans[i] = s;
        }
        return ans;
    }
    
    static int ceil(long[] ar, long x) {
        int l = 0, r = ar.length;
        while (l + 1 < r) {
            int m = (l + r) >> 1;
            if (ar[m] > x) {
                r = m;
            } else if (ar[m] < x) {
                l = m;
            } else {
                l = m;
            }
        }
        return r;
    }
    
    static int merge(long[] first, long[] second, int v) {
        int s = 0;
        for (int i = 0; i < first.length; i++) {
            if (first[i] > v) break;
            else {
                s += ceil(second, v - first[i]);
            }
        }
        return s;
    }
    
    static int solve(int[] a, int v) {
        Arrays.sort(a);
        long[] first = build(a, 0, a.length / 2);
        long[] second = build(a, a.length / 2, a.length);
        Arrays.sort(first);
        Arrays.sort(second);
        return merge(first, second, v);
    }
    
    public static void main(String[] args) throws FileNotFoundException {
    //    Scanner cin = new Scanner(System.in);
        Scanner cin = new Scanner(new FileInputStream("in.txt"));
        int n = cin.nextInt();
        int v = cin.nextInt();
        int[] a = new int[n];
        for (int i = 0; i < n; i++) a[i] = cin.nextInt();
        cin.close();
        if (n == 1) {
            System.out.println("1");
        } else {
            int ans = solve(a, v);
            System.out.println(ans);
        }
    }
    }
    
  • 相关阅读:
    如何在Windows 7平台搭建Android Cocos2d-x3.2alpha0开发环境
    boost::unordered_map分析和使用(转)
    #、##、__VA_ARGS__和##__VA_ARGS__的作用(转)
    C++ explicit关键字详解(转)
    C++11的auto关键字
    Nagios监控系统
    CentOS6.5安装oracle11
    Centos7系统中Mysql登录忘记root密码
    在Centos7系统上查看Mysql版本的方法
    忘记Redhat7root密码
  • 原文地址:https://www.cnblogs.com/weiyinfu/p/8660879.html
Copyright © 2011-2022 走看看