名企笔试:Aamazon笔试题(Number of Groups )

Aamazon笔试题(Number of Groups )
题意:
Given an array Arr[] of N distinct integers. Write a program to find the count of groups of 2 or 3 integers that can be formed by choosing integers from the given array such that sum of integers in each of the group is divisible by three.
给你一个带有N个不同整数的数组,问能够选择出来多少组只有2个或者3个的组的和被3整除。
输入描述:
第一行表示测试的组数,第二行是n的大小,接下来是输入数组。
输出描述:
每一测试输出一个数,表示组数。

Constraints:
1<=T<=100
1<=N<=105
1<=Arr[i]<=105
Example:
Input:
2
6
1 5 7 2 9 14
4
3 6 9 12
Output:
13
10
分析:
暴力解决问题?当然可以。只需要一个两层训练+一个三层循环就直接出来结果。但是出来在笔试或者面试时,只给出这种答案,面试官可是不怎么高兴的,而且对于本题的数组范围,应该也会超时。解决这个题,我们有一个有关余数的定理,对于一个k,如果n%k = a,m%k = b,则有(n+m) % k = (n%k + m%k) % k = (a+b) % k,如果(a+b)%k = 0,则有(n+m)%k = 0。有了上面这个定理,我们只需要纪录数组中余数0,1,2的个数,从0,1,2中进行2个数或者3个数的组合计数,就可以得到结果,能够被3整除的情况共有如下几种:
1、 0+0 (选择两个能够被三整除的数)
2、 0+0+0 (选择3个能够被三整除的数)
3、 1+2 (选择1个余数是1的数和一个余数是2的数)
4、0+1+2 (选择1个余数是1的数和一个余数是2的数和一个余数是0的数)
5、 1+1+1 (选择3个余数是1的数)
6、 2+2+2 (选择3个余数是2的数)
假如数组c[3]表示余数的个数,c[0]表示余数是0的个数,c[1]表示余数是1的个数,c[2]表示余数是2的个数,上述对应的情况的个数如下:
1、 c[0]*(c[0]-1)/2
2、 c[0](c[0]-1)(c[0]-2) / 6;
3、 c[1]*c[2];
4、 c[0]*c[1]*c[2];
5、 c[1](c[1]-1)(c[1]-2) / 6;
6、 c[2](c[2]-1)(c[2]-2) / 6;
相加就得到结果。

Code:

/**
 *Author: xiaoran
 *座右铭:既来之,则安之
 */
/**
 * 
 *从一个数组中,选出2或者3个数,使得他们的和能够被3整除,
 * 为有多少中选择的方式。
 * 余数定理,如果a % 3 = 1,b % 3 = 2则 (a+b)%3=0
 * 我们只需要纪录每个数模3之后的余数的个数,从余数中进行2、3组合即可
 * 共有以下集中情况:直接用0,1,2表示余数为0,1,2的数字
 * 1、 0+0 (选2个能够被3整除的数)
 * 2、 0+0+0 (选3个能够被3整除的数)
 * 3、 1+2
 * 4、 0+1+2
 * 5、 1+1+1
 * 6、 2+2+2
 */
#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<math.h>
#include<set>
#include<map>
#include<vector>
#include<string>
#include<string.h>
using namespace std;
typedef long long LL;

const int MAXN = 1005;
int main() {
    //code
    int t,n,x;
    cin>>t;
    while(t--){
        cin>>n;
        int c[3] = {0};
        for(int i=0;i<n;i++){
            cin>>x;
            c[x%3]++;
        }
        int sum = 0;
        // 按照上述的情况进行加法原则
        sum += c[0]*(c[0]-1) / 2;
        sum += c[0]*(c[0]-1)*(c[0]-2) / 6;
        sum += c[1]*c[2];
        sum += c[0]*c[1]*c[2];
        sum += c[1]*(c[1]-1)*(c[1]-2) / 6;
        sum += c[2]*(c[2]-1)*(c[2]-2) / 6;

        cout<<sum<<endl;
    }

    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值