个人积分赛7

D.Make Them Odd

题面如下:

There are n positive integers a1,a2,,an. For the one move you 
can choose any even value c and divide by two all elements that
 equal c.
For example, if a=[6,8,12,6,3,12]and you choose c=6,
 and a is transformed into a=[3,8,12,3,3,12]after the move.
You need to find the minimal number of moves for transforming a
to an array of only odd integers (each element shouldn't be 
divisible by 2).
Input:
   The first line of the input contains one integer t(1≤t≤104) —
the number of test cases in the input. 
Then t test cases follow.
The first line of a test case contains n(1≤n≤2105) — 
the number of integers in the sequence a. 
The second line contains positive integers a1,a2,,an(1≤ai≤109).
The sum of n for all test cases in the input doesn't exceed 2105.
Output:
    For t test cases print the answers in the order of test cases
in the input. The answer for the test case is the minimal number 
of moves needed to make all numbers in the test case odd 
(i.e. not divisible by 2).
Example
    Input:
    4
    6
    40 6 40 3 20 1
    1
    1024
    4
    2 4 8 16
    3
    3 1 7

    Output:
    4
    10
    4
    0


本题的大致题意为:一共t组查询,每组n个数,每一次可将该数组里相同的偶数同时除以2,直到该数组里所有的数都为奇数。
核心思路为我们需要用一个数组将偶数的变化过程标记下来,如果循环到某偶数且当前数字未被标记就开始当前循环,若被标记或当前为奇数,则循环结束,每次循环记录一共除的总次数即可。
代码实现:

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<math.h>
#include<iostream>
#include<algorithm>
#include<map>
using namespace std;
#define hhh 3000005
int cmp(int x,int y){
	return x>y;
}
int a[hhh];
int main(){
	int t,n,ans;
	scanf("%d",&t);
	while(t--){                                 //多组 
	    ans=0;
		scanf("%d",&n);
		for(int i=1;i<=n;i++){
			scanf("%d",&a[i]);
		}	
		sort(a+1,a+n+1,cmp);                    //快排 使从大到小选择偶数 进行运算  
		map<int,int>flag;                       //a[i]最大为10的9次,用普通数组定义装不下 
		for(int i=1;i<=n;i++){
			if(a[i]%2==0){                      //若为偶数,则进行下列运算 
				while(a[i]%2==0&&flag[a[i]]==0){//当该数是偶数,且未被标记过,则标记,并将其除2 
					flag[a[i]]=1;               //标记的作用是使与其相同的数不会被重复除 
					a[i]=a[i]/2;
					ans++;                      //记录除的次数 
				}
			}
		}
		printf("%d\n",ans);
	}
	return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值