LuoguP6747 『MdOI R3』Teleport 二进制+贪心
令 $f[i]$ 表示考虑第 $1$ ~ $i$ 位的最小代价.
由于要求最大化 $k$,所以从高位向低位贪心.
判断的话就判一下当前二进制位选 1 的代价加上 $f[i-1]$ 是否小于等于 m.
如果可以选就贪心选 1.
这道题比较容易爆精度,long long 可能会乘爆,所以判一下两个 long long 相乘是否为负数.
代码:
#include <cstdio> #include <cstring> #include <algorithm> #define N 100009 #define ll long long #define M 52 #define setIO(s) freopen(s".in","r",stdin) using namespace std; int n; ll b0[60],b1[60]; ll a[N],f[60],bin[60]; int main() { //setIO("input"); scanf("%d",&n); for(int i=0;i<M;++i) bin[i]=1ll<<i; for(int i=1;i<=n;++i) { scanf("%lld",&a[i]); for(int j=0;j<M;++j) { if(a[i]&bin[j]) { ++b1[j]; } else { ++b0[j]; } } } f[0]=min(b1[0],b0[0]); for(int i=1;i<M;++i) { f[i]=bin[i]*min(b0[i],b1[i])+f[i-1]; } int Q; scanf("%d",&Q); for(int i=1;i<=Q;++i) { ll det,k=0; int flag=0; scanf("%lld",&det); for(int j=M-1;j;--j) { if(bin[j]*b0[j]>=0&&bin[j]*b0[j]+f[j-1]<=det) { k^=bin[j]; det-=bin[j]*b0[j]; } else if(bin[j]*b1[j]>=0&&bin[j]*b1[j]+f[j-1]<=det) { det-=bin[j]*b1[j]; } else { flag=1; printf("-1\n"); break; } } if(flag==1) { continue; } else { if(b0[0]<=det) k^=1; else if(b1[0]<=det) k^=0; else { printf("-1\n"); continue; } printf("%lld\n",k); } } return 0; }