题意:给出长度为n的数组,每次操作可以使得a[i]=a[i]*i;求最少次数的操作使得所有数的乘积能够整除2^n。
思路:转为题意即是要满足n个2因子,可以首先遍历数组a,求得每个偶数的2的因子个数,看是否>=n,若<n,则要进行操作,很容易就可以发现当i为偶数时才会对答案有贡献,因此再求每个偶数下标所含有的2的因子个数,然后从大到小排序,2因子个数多的优先,这样下来一定是最优策略了,如果全部下标遍历还未满足n个因子数,输出-1。求因子个数可以先用lowbit函数求得最小的1与后面的0组成的数,然后不断除以2,就可以求出当前偶数所含有2因子的个数。因为要求2因子个数的数都是偶数,所以lowbit函数返回的值一定是2^1,2^2,2^3,2^4........
AC code:
#include <bits/stdc++.h>
#define int long long
using namespace std;
int t, n, a[200010], b[200010];
signed lowbit(int x)
{
return x & (-x);
}
void solve()
{
cin >> n;
// int sum = (1 << n);
// for(int i = 1; i <= n; i++)
// {
// cin >> a[i];
// if(a[i] % 2 == 0)
// {
// sum /= (lowbit(a[i]));
// }
// b[i] = 0;
// }
// if(sum <= 1)
// {
// cout << 0 << endl;
// return ;
// }
// int cnt = 0;
// for(int i = 2; i <= n; i += 2)
// {
// b[i] = lowbit(i);
// }
// sort(b + 1, b + n + 1, greater<int>());
// for(int i = 1; i <= n; i++)
// {
// if(b[i] == 0)
// {
// break;
// }
// if(sum <= b[i])
// {
// cout << cnt + 1 << endl;
// return ;
// }
// else
// {
// sum /= b[i];
// cnt++;
// }
// }
// if(sum > 1)
// {
// cout << -1 << endl;
// }
// else
// {
// cout << cnt << endl;
// }
int cnt=0;
for(int i=1;i<=n;i++){
cin>>a[i];
b[i]=0;
if(a[i]%2==0 && cnt<n){
int x=lowbit(a[i]);
while(x>1){
x/=2;
cnt++;
}
}
}
if(cnt>=n){
cout<<0<<endl;
return ;
}
for(int i=2;i<=n;i+=2){
b[i]=lowbit(i);
}
sort(b+1,b+n+1,greater<int>());
int t=n-cnt;
cnt=0;
// cout<<t<<endl;
for(int i=1;i<=n;i++){
if(b[i]==0){
break;
}
while(cnt<t && b[i]>1){
b[i]/=2;
cnt++;
}
if(cnt>=t){
cout<<i<<endl;
return ;
}
}
cout<<-1<<endl;
}
signed main()
{
cin >> t;
while(t--)
{
solve();
}
return 0;
}
最开始想的是求因子个数,然后想了下后面还要不断除以2求2因子个数,感觉没必要,就准备1<<n直接依次除,结果交了后发现n==20000时,恰好是这个最大值,就超范围了。。。然后又改为求因子。。。