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);
    }
}

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

posted @ 2020-03-01 01:39  守林鸟  阅读(842)  评论(0编辑  收藏  举报