Codeforces Round #828 (Div. 3) D.Divisibility by 2^n(暴力/思维)
题目写多了,人也越来越怂了
也许是没有休息好吧哈哈,读了半个多小时的假题,最后还因为把一个>写成了!导致没开出来
1200的题目都没写出来,真是废物一个啊
D.Divisibility by 2^n
https://codeforces.com/contest/1744/problem/D
题目大意:
给定一个长度为n的数组a,我们要使数组中全部数字的乘积乘起来最后可以整除2^n;
我们可以考虑【0,n】次,每次选择一个下标把它乘到某一个数字中(注意每个下标只能选择一次)。
问可以整除2^n的最小操作是多少?
input
6
1
2
2
3 2
3
10 6 11
4
13 17 1 1
5
1 1 12 1 1
6
20 7 14 18 3 5
output
0
1
1
-1
2
1
这个题目我觉得很多人不敢写的原因大多数应该都是见到了这个数据范围吧 n(1≤n≤2⋅10^5) a[i] (1≤ai≤10^9).
然而其实都是纸老虎
我们只需要整除2^n,所以我们只需要保证全部乘起来的数字至少内部包含有n个2就行了
这样就到了数一数的环节
我们得到了所给数组中的2,如果足够的话那就直接输出;但是如果不够呢?
不够的时候我们就可以借助下标中的2来帮助扩展一下,那么怎么得到下标中的2呢?
也是直接预处理就行了【别怂啊,才2e5的数据范围,怕什么,直接冲就完了】
然后因为是要取最小操作数嘛,直接从大到小一直减下来就行了
暴力贯穿全文,nice!
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<LL,LL> PII;
const LL N=500200,M=2002;
LL a[N];
int main()
{
cin.tie(0); cout.tie(0); ios::sync_with_stdio(false);
LL T=1;
cin>>T;
while(T--)
{
LL n;
cin>>n;
LL sum2=0;
for(LL i=1;i<=n;i++)
{
cin>>a[i];
}
vector<LL> v;
for(LL i=1;i<=n;i++)
{
LL idx=i,num=0;
while(idx%2==0)
{
idx/=2;
num++;
}
if(num!=0) v.push_back(num);
while(a[i]%2==0)
{
a[i]/=2;
sum2++;
}
}
if(sum2>=n) cout<<"0"<<endl;
else
{
LL last=n-sum2;//还需要多少个2
LL ans=0;
sort(v.rbegin(),v.rend());
//for(int i=0;i<v.size();i++)
// cout<<v[i]<<" ";
//cout<<endl;
for(LL i=0;i<v.size();i++)
{
if(last>0)
{
last-=v[i];
ans++;
}
if(last<=0) break;
}
if(last>0) cout<<"-1"<<endl;
else cout<<ans<<endl;
}
v.clear();
}
return 0;
}
- 多睡觉,睡醒了脑子才清醒!!!不然1200的题目都写不出。。。