Array Reodering


题目

You are given an array a consisting of n integers.
Let’s call a pair of indices i,j good if 1≤i<j≤n and gcd(ai,2aj)>1 (where gcd(x,y) is the greatest common divisor of x and y).
Find the maximum number of good index pairs if you can reorder the array a in an arbitrary way.
Input
The first line contains a single integer t (1≤t≤1000) — the number of test cases.
The first line of the test case contains a single integer n (2≤n≤2000) — the number of elements in the array.
The second line of the test case contains n integers a1,a2,…,an (51≤ai≤105).
It is guaranteed that the sum of n over all test cases does not exceed 2000.
Output
For each test case, output a single integer — the maximum number of good index pairs if you can reorder the array aa in an arbitrary way.
Example
Input
3
4
3 6 5 3
2
1 7
5
1 4 2 4 1
Output
4
0
9
Note
In the first example, the array elements can be rearranged as follows:[6,3,5,3].
In the third example, the array elements can be rearranged as follows: [4,4,2,1,1].

题意:

给你一个序列a[l~n],求满足1<=i<=j<=n,__gcd(a[i],2*a[j])的良好索引对(i,j)的数量。

思路:

一开始看到题目的时候有点懵了,然后看到题目下面的提示还以为要先找出最佳的排列顺序在进行下面的操作,然后就卡了这道题,到最后才发现没那么难,其实要想求最佳索引对的数量,只需将偶数都放在排序的前面,让偶数做的贡献便到最大,然后把1放到最后,其他奇数放到中间即可,因为是求a[i]与2a[j]的最大共同因子是否大于1,所以a[i]如果为偶数a[i]与2a[j]必有共同因子2此时(i,j)一定是良好索引对,如果a[i]为奇数的话就直接循环判断(i,j)是否为良好索引对就行了.

代码如下

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cmath>
#include <cstring>
using namespace std;
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int num=0;
        int n;
        scanf("%d",&n);
        int a[n+1];
        int c[n+1];
        memset(a,0,sizeof(a));
        memset(c,0,sizeof(c));
        int x=1;
        int k=1;
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
            if(a[i]%2==0)
            {
                num=num+n-k;
                k++;
                // cout<<num<<endl;
            }
            else if(a[i]%2!=0)
            {
                c[x++]=a[i];
            }
        }
        for(int i=1;i<x;i++)
        {
            for(int j=i+1;j<x;j++)
            {
                if(__gcd(c[i],c[j]*2)>1) num++;
            }
                
        }
        printf("%d\n",num);
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值