题意:
题意:
给定一个数组,每次操作可以使得a[i]*=i,每次操作的下标不得重复,问最少多少操作使得数组乘积能被2^n整除
思路:贪心+贡献
考虑贡献
先处理出数组2的因子个数,若一开始因子个数>=n,那么不需要进行任何操作,输出0
若因子个数<n,那么需要对一些位置乘 i
因为是最少操作,因此我们希望一次乘i对因子2的个数的贡献尽可能大,所以需要预处理1到n数字中因子2的个数,然后排序之后优先对因子2个数大的下标进行操作
Code:
#include <bits/stdc++.h>
using namespace std;
const int mxn=2e5+10;
#define int long long
vector<pair<int,int> > v;
int n,tmp,sum=0,sum2=0;
int a[mxn];
bool cmp(pair<int,int> a,pair<int,int> b){
return a.second>b.second;
}
void solve(){
sum=0,sum2=0;
v.clear();
cin>>n;
for(int i=1;i<=n;i++){
sum2=0;
cin>>a[i];
tmp=a[i];
while(tmp%2==0) sum++,tmp/=2;
tmp=i;
while(tmp%2==0) sum2++,tmp/=2;
if(sum2) v.push_back({i,sum2});
}
sort(v.begin(),v.end(),cmp);
int res=n-sum,ans=0;
if(sum>=n) cout<<0<<'\n';
else{
for(int i=0;i<v.size();i++){
if(v[i].second<=res){
ans++;
res-=v[i].second;
}
}
if(res) cout<<-1<<'\n';
else cout<<ans<<'\n';
}
}
signed main(){
int T;
cin>>T;
while(T--)solve();
return 0;
}