Codeforces Round #606 (Div. 2, based on Technocup 2020 Elimination Round 4)
题目链接:http://codeforces.com/contest/1277/problem/B
测试样例:
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
Note
In the first test case of the example, the optimal sequence of moves can be as follows:
- before making moves a=[40,6,40,3,20,1]a=[40,6,40,3,20,1];
- choose c=6c=6;
- now a=[40,3,40,3,20,1]a=[40,3,40,3,20,1];
- choose c=40c=40;
- now a=[20,3,20,3,20,1]a=[20,3,20,3,20,1];
- choose c=20c=20;
- now a=[10,3,10,3,10,1]a=[10,3,10,3,10,1];
- choose c=10c=10;
- now a=[5,3,5,3,5,1]a=[5,3,5,3,5,1] — all numbers are odd.
Thus, all numbers became odd after 44 moves. In 33 or fewer moves, you cannot make them all odd.
题目大意:
每次选择一个偶数变为奇数,最终将所有数字全部变为奇数,寻找最小变换次数。变换规则为将偶数除以2,可将其等大小的同时变换。
思路:
为了寻找最小变换次数,理论上从最大的偶数开始做除以2变换,直到变为奇数或者是出现过的数字。变为出现过的就停止变换,则是可以留着后面一起变换,减少变换次数。代码方面则可以从小到大遍历,当大的变为出现过的时,可认为不需要再次变换了。
AC代码:
#include<bits/stdc++.h>
using namespace std;
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int n;
scanf("%d",&n);
int cnt=0;
map<int,int> mp;
for(int i=0;i<n;i++)
{
int x;
scanf("%d",&x);
mp[x]++;
}
for(map<int,int>::iterator it=mp.begin();it!=mp.end();it++)
{
if(it->second&&it->first%2==0)
{
int num=it->first;
while(num&&num%2==0)
{
num>>=1;
cnt++;
if(mp[num])
break;
}
}
}
printf("%d\n",cnt);
}
return 0;
}
解题过程:
开始使用数组标记数字,当输入数字n,a[n]++,表示n出现过。但这样数组会越界,因为数字范围超出了数组范围,也开不了数字最大值大小的数组。
然后开始尝试用map来标记,发现用不来迭代器,跑去查迭代器用法。。。。。。