1 条题解

  • 0
    @ 2025-8-25 18:34:19

    O(NlogN)O(NlogN) 贪心

    1. 问题转化

      • 设初始乘积为 P=a1×a2××anP = a_1 \times a_2 \times \cdots \times a_n
      • 我们需要 P×(i1i2ik)P \times (i_1 \cdot i_2 \cdot \cdots \cdot i_k) 能被 2n2^n 整除,其中 iji_j 是操作选择的编号。
    2. 关键观察

      • 实际上,我们只需要关心乘积中因子 2 的个数。
      • 设初始乘积 PP 中因子 22 的个数为 cntcnt
      • 我们需要通过操作增加至少 ncntn - cnt 个因子 22
    3. 操作的影响

      • 每次选择编号 ii 进行操作,会额外引入因子 22 的个数等于 ii 中因子 22 的个数。
      • 例如,选择编号 44 会引入 22 个因子 22
    4. 贪心策略

      • 计算每个编号 ii 能提供的因子 22 的个数.
      • 将这些因子 22 的个数从大到小排序,优先选择提供因子 22 多的操作。
      • 累计因子 22 的个数,直到达到或超过 ncntn - cnt
    5. 特殊情况

      • 如果初始 cntncnt \geq n,则不需要操作(输出 0 )。
      • 如果所有操作后累计的因子 22 仍然小于 ncntn - cnt ,则输出 1-1
    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    const int N=2e5+10;
    int a[N], b[N];
    bool cmp(int x, int y){
    	return x>y;
    }
    void solve() {
    	int t;
    	cin >> t;
    	while(t--) {
    		int n;
    		cin >> n;
    		int ans=0;
    		for(int i=1; i<=n; i++){
    			cin >> a[i];
    			while(a[i]%2==0){
    				ans++;
    				a[i]/=2;
    			}
    			int k=i;
    			b[i] = 0; //初始化 
    			while(k%2==0){
    				b[i]++;
    				k/=2;
    			}
    		}
    		if(ans>=n) {
    			cout << 0 << '\n';
    			continue;
    		}
    		sort(b+1, b+1+n, cmp);
    		for(int i=1; i<=n; i++){
    //			cout << b[i]<<' ';
    			ans+=b[i];
    			if(ans>=n){
    				cout << i <<'\n';
    				break;
    			}
    		}
    		if(ans<n) cout<<-1<<'\n';
    	}
    }
    int main() {
    //	ios::sync_with_stdio(false);
    //	cin.tie(0), cout.tie(0);
    	solve();
    	return 0;
    }
    
    • 1

    信息

    ID
    575
    时间
    1000ms
    内存
    256MiB
    难度
    10
    标签
    递交数
    6
    已通过
    1
    上传者