Codeforces Round #828 (Div. 3)D

题目链接:Problem - D - Codeforces

题意:给出长度为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时,恰好是这个最大值,就超范围了。。。然后又改为求因子。。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值