Test Generator
题意简述
给定两个整数 ( s ) 和 ( m ),需要构造一个非负整数数组 ( a ),满足:
- 数组元素之和等于 ( s );
- 每个元素 ( a_i ) 的二进制位中,为 1 的位必须是 ( m ) 的二进制位中也为 1 的位(即 ( a_i & m = a_i ))。
要求判断是否存在这样的数组。若存在,输出数组的最小可能长度 ( n );否则输出 (-1)。
#include <bits/stdc++.h>
using namespace std;
using ll=long long;
void so(){
ll s,m;cin>>s>>m;
ll ans=0;
int ok=0;
ll k=s;
for(int i=0;i<=62;i++){
if((m>>i)&1){
if(k%(1ll<<i)==0)ok=1;
break;
}//至少可以由最第低位构成
}if(ok==0){cout<<-1<<'\n';return;}
ll l=1,r=1e18;
while(l<=r){
ll mid=(l+r)/2;
s=k;
for(int i=62;i>=0;i--){
if((m>>i)&1){
ll d=min(mid,s/(1ll<<i));//优先用大的
//不可以超过mid次
s-=d*(1ll<<i);
}
}if(s>0){
l=mid+1;//不够再加
}else r=mid-1;
//最后l>r;
//当<=0,r去试更小的
}cout<<l<<'\n';
}int main(){
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
int t;cin>>t;
while(t--){so();}
}
注意与启示
1.求最短的,可以想到二分
2.先不要看s,m有1的话s马上减,最多只能减mid(大的数先能用几次先用)