zoukankan      html  css  js  c++  java
  • NOJ1366: [蓝桥杯2018初赛]倍数问题-(思维)

    题目描述

    众所周知,小葱同学擅长计算,尤其擅长计算一个数是否是另外一个数的倍数。 
    但小葱只擅长两个数的情况,当有很多个数之后就会比较苦恼。 
    现在小葱给了你 n 个数,希望你从这 n 个数中找到三个数 
    使得这三个数的和是 K 的倍数,且这个和最大。数据保证一定有解。 

    输入

    第一行包括 2 个正整数 n, K。
    第二行 n 个正整数,代表给定的 n 个数。
    1 <= n <= 10^5, 1 <= K <= 10^3,给定的 n 个数均不超过 10^8。

    输出

    输出一行一个整数代表所求的和。

    样例输入 Copy

    4 3
    1 2 3 4

    样例输出 Copy

    9

    思路:假设三个数分别是a,b,c;(a+b+c)%k=(a%k+b%k+c%k)%k=0。限定了k<1000则每个数的模数必然<k,最多取三个,对于每种模数保留三个最大的情况。还要对三个数的模数想等情况做出判断,互不相等、有两个相等、全部不相等。用一个num数组记录模数的个数看看三个数的模数是否满足需求。A组第9题居然能想出来,多亏之前的k倍区间给我提供了模数和的思路。

    import java.util.*;
    
    import java.util.Collections;
     
    public class Main{//1366: [蓝桥杯2018初赛]倍数问题
        
        public static void main(String []args){    
            Scanner scan=new Scanner(System.in);
            
            int [][] mod=new int[1005][3];//相同模数保留前三大的
            int [] num=new int[1005];
            int n=scan.nextInt();
            int p=scan.nextInt();    
            for(int i=1;i<=n;i++) {
                int x=scan.nextInt();
                int r=x%p;
                num[r]++;
                //找到这个模数的最小的一个数 和 下标
                int minn=Integer.MAX_VALUE;
                int idx=0;
                for(int j=0;j<3;j++) {
                    if(minn>mod[r][j]) {
                        idx=j;
                        minn=mod[r][j];
                    }
                }
                if(minn<x)//x比原来的大,取代原来的那个
                    mod[r][idx]=x;
                
            }
    
            long maxx=0;
            for(int i=0;i<p;i++) 
                Arrays.sort(mod[i]);
            
            //双重暴力 最后一个数用减法即离散化即可定位模数下标
            for(int i=0;i<p;i++) {
                for(int j=0;j<p && num[i]!=0;j++) {
                    long now=0;
                    int k=p-((i+j)%p);
                    if(i==j && i==k ) {///三个模数都相同
                        if(num[i]>=3)
                            now=mod[i][2]+mod[i][1]+mod[i][0];    
                    }else if(i==j && i!=k) {//前两个模数相同
                        if(num[i]>=2 && num[k]>=1)
                            now=mod[i][2]+mod[i][1]+mod[k][2];
                        
                    }else if(i!=j && j==k) {//后两个模数相同
                        if(num[i]>=1 && num[j]>=2)
                            now=mod[i][2]+mod[j][2]+mod[j][1];
                    }else if(i==k && i!=j){//第一个和第三个相同
                        if(num[i]>=2 && num[j]>=1)
                            now=mod[i][2]+mod[i][1]+mod[j][2];
                    }else {//三个模数都不同
                        if(num[i]>=1 && num[j]>=1 && num[k]>=1 )
                            now=mod[i][2]+mod[j][2]+mod[k][2];
                    }
                    if(maxx<now)
                        maxx=now;
                }
            }
            System.out.println(maxx);
        }
    }

     天上不会掉馅饼,努力奋斗才能梦想成真。

  • 相关阅读:
    225. Implement Stack using Queues
    232. Implement Queue using Stacks
    LeetCode 763 划分字母区间
    CentOS7+eDEX-UI打造属于你的极客桌面
    好玩又有趣的linux终端命令
    Linux 应急响应入门——入侵排查
    active_anon/inactive_anon
    Red Hat 平台的推荐交换大小是多少?
    为什么RHEL系统使用交换空间而不是释放缓存和缓冲内存?
    RHEL 交换内存(Swap)使用率为 100%
  • 原文地址:https://www.cnblogs.com/shoulinniao/p/12387679.html
Copyright © 2011-2022 走看看