一道很喜欢很有趣的题目
这道题目用 m a p map map来做会非常便利并且好实现!我愿将其称之为 G r e a t P r o b l e m ! Great\ Problem\ ! Great Problem !
来自 c f D i v . 1 cf\ Div.1 cf Div.1
思路:
根据题意,我们可以想到 运用 m a p map map会很容易实现将输入序列按从大到小排序且可以获得每个输入序列元素的数量,这正是这道题目的关键!
通过 m a p map map以上的功能,我们来分析这题的解题思路:
我们遍历 m a p map map ,每次将最小的元素(也就是 m a p map map中当前最前面的元素)乘 x x x,此处命名为 n u m num num,,并查找 m a p map map中是否存在 n u m num num,并且如果 m a p map map中没有这个元素,那么说明我们需要添加额外的数来满足题意,那么我们定义一个计数器 c n t cnt cnt来统计需要额外增加多少数,并且此处将 c n t + cnt+ cnt+此时的元素的数量,如果 m a p map map中存了 n u m num num这个数据,那么我们需要比较二者的数量,如果 n u m num num的数量多,那么将 n u m num num的数量 − - − 当前元素的数量,也就是得到在与当前元素匹配完 n u m num num还剩几个。如果当前元素的数量比 n u m num num的数量多,那么说明 m a p map map中的元素数量不够匹配,那么我们也需要添加额外的数来满足题意,那么此时我们将 c n t + cnt+ cnt+ 需要增加的额外的数量,同时! 要 e r a s e ( n u m ) erase(num) erase(num) !否则,下一轮遍历仍然会遍历到 m a p map map,即使 第二键值为 0 0 0!所以 ,只要 元素个数不为 0 0 0,我们就对其遍历查找。
#include <bits/stdc++.h>
#define int long long
using namespace std;
signed main(){
ios_base::sync_with_stdio(0),cin.tie(0),cout.tie(0);
int t,n,x,a; cin >> t;
map<int,int>mp;
while(t--){
mp.clear();
cin >> n >> x;
int num=0,cnt=0;
for(int i=0;i<n;i++) cin >> a,mp[a]++;
for(auto i : mp){
num=i.first*x;
if(mp.count(num)){
if(i.second>=mp[num]) cnt+=i.second-mp[num],mp.erase(num);
else mp[num]-=i.second;
}
else cnt+=i.second;
}
cout << cnt << endl;
}
return 0;
}
注意: 这题在乘法那一步会爆 i n t int int!
d e f i n e i n t l o n g l o n g define\ int\ long\ long define int long long还是很有必要的!
Debug过程中发现的问题:
-
如果 我们定义的迭代器不加 & \& & 那么我们无法按改变当前的第二键值,相反加了就可以~
-
还有一个点在上面提过了,只要一个元素存在了 m a p map map中,不管它的 s e c o n d second second是否为 0 0 0,只要不 e r a s e erase erase它,在后续遍历中依然会遍历到它!