C. Great Sequence(Div. 2)

题目:

A sequence of positive integers is called great for a positive integer x, if we can split it into pairs in such a way that in each pair the first number multiplied by x is equal to the second number. More formally, a sequence a of size n is great for a positive integer x, if n is even and there exists a permutation p of size n, such that for each i (1≤i≤n2) ap2i−1⋅x=ap2i.

Sam has a sequence a and a positive integer x. Help him to make the sequence great: find the minimum possible number of positive integers that should be added to the sequence a to make it great for the number x.

Input
Each test contains multiple test cases. The first line contains a single integer t (1≤t≤20000) — the number of test cases. Description of the test cases follows.

The first line of each test case contains two integers n, x (1≤n≤2⋅105, 2≤x≤106).

The next line contains n integers a1,a2,…,an (1≤ai≤109).

It is guaranteed that the sum of n over all test cases does not exceed 2⋅105.

Output
For each test case print a single integer — the minimum number of integers that can be added to the end of a to make it a great sequence for the number x.

Example
inputCopy
4
4 4
1 16 4 4
6 2
1 2 2 2 4 7
5 3
5 2 3 5 15
9 10
10 10 10 20 1 100 200 2000 3
outputCopy
0
2
3
3
Note
In the first test case, Sam got lucky and the sequence is already great for the number 4 because you can divide it into such pairs: (1,4), (4,16). Thus we can add 0 numbers.

In the second test case, you can add numbers 1 and 14 to the sequence, then you can divide all 8 integers into such pairs: (1,2), (1,2), (2,4), (7,14). It is impossible to add less than 2 integers to fix the sequence.

题意:

对于一个正整数序列,将其元素两两分为一对,使得每队中元素 a 乘 x 等于元素 b。
现有一个长度为 n 的正整数序列,为满足上述条件,求至少需要向本序列中添加几个元素。

思路:

数组 a 存初始序列,升序排列数组,遍历数组中的元素,看有多少元素不满足 a[i] * x == a[j]。
由于已配对元素不需要再考虑,故数组我用了动态数组vector,取其erase函数用来删除元素。

代码:

#include <iostream>
#include <cstdio>
#include <string.h>
#include <set>
#include <algorithm>
#include <vector>

typedef long long ll;
using namespace std;

vector<int> v;

bool half_find(int l,int r,int x){//二分查找
    int ha;
    while(l<r){
        ha = (l+r)/2;
        if(v[ha]==x){
            v.erase(v.begin()+ha);
            return true;
        }
        else if(v[ha]>x)
            r = ha;
        else
            l = ha+1;
    }
    if(v[l]==x){
        v.erase(v.begin()+l);
        return true;
    }else
        return false;
}

int main(){
    int t;
    scanf("%d",&t);
    while(t--){
        int n,ans=0,x;
        scanf("%d%d",&n,&x);
        for(int i=0;i<n;i++){
            int a;
            scanf("%d",&a);
            v.push_back(a);
        }
        sort(v.begin(),v.end());
        vector<int>::iterator it;
        for(it = v.begin();it != v.end();it++){
            //如果乘积大于序列中最大的数字
            //那么剩余的数字都无法配对
            ll tem = ll(*it) * ll(x);//不用long long 会溢出
            if(tem > v[v.size()-1]){
                ans+=v.end()-it;
                break;
            }
            // it - v.begin() 即当前元素在数组中的下标
            if(!half_find(it-v.begin(),v.size()-1,*it * x))
                ans++;
        }
        printf("%d\n",ans);
        v.clear();
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值