题目
多组样例,n(n<=5e6)种机器,第i种机器有ai和bi两个权值,用上述算法生成,其中参数1<=k1,k2<=1e12
对于第i种机器,你可以按一次按钮获得ai收益,可以再按一次再获得bi收益,可以再按第三次获得ai收益,最多按三次
记f(x)为只能按x次按钮的最大收益和,
求f(1)^f(2)^...^f(m)(m<=1.5e7),其中^表示异或
思路来源
官方题解
心得
赛中一直考虑1、2、3三种怎么互斥背包,然而1.5e7决定了只能用线性做,
感觉主要是没想到拆成两个无关的物品然后贪心吧
题解
考虑第i种,1次ai,2次ai+bi,3次ai+(ai+bi),
可以拆成两个约束无关的物品,一个(1,ai),一个(2,ai+bi),对应次数和权值
如果考虑用平均值最高的物品凑出x次,则可能凑出的是x+1次,
此时一个2次数的平均比一个1次数的更优,
这种情况下,把已经取的2次数的平均最小的去掉,把1次数的还没取的最大的加上,就是f(x)的值,
因此,可以考虑递推,f(x)从f(x-1)次递推而来,
要么,选择一个还没取的权值最大的1次,
要么,把已经取的2次的权值最小的去掉,把1次数的还没取的最大的加上
复杂度O(nlogn+m)
代码
#include<bits/stdc++.h>
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
const int N=5e6+10,M=15e6+10,mod=1e9+7;
const int mx=10000000;
ull k1,k2;
int t,n,m,a[N],b[N];
ll ans,now;
ull xorS(){
ull k3=k1,k4=k2;
k1=k4;
k3^=(k3<<23);
k2=k3^k4^(k3>>17)^(k4>>26);
return k2+k4;
}
void gen(int n,ull _k1,ull _k2){
k1=_k1,k2=_k2;
for(int i=1;i<=n;++i){
a[i]=xorS()%mx+1;
b[i]=xorS()%mx+1;
}
}
int main(){
while(~scanf("%d%d%llu%llu",&n,&m,&k1,&k2)){
gen(n,k1,k2);
for(int i=1;i<=n;++i){
b[i]=a[i]+b[i];
}
sort(a+1,a+n+1,greater<int>());
sort(b+1,b+n+1,greater<int>());
ans=a[1];now=a[1];
int na=1,nb=0;
for(int i=2;i<=m;++i){
ll v1=0,v2=0;
if(na+1<=n){
v1=now+a[na+1];
}
if(na-1>=0 && nb+1<=n){
v2=now-a[na]+b[nb+1];
}
if(v1>v2){
na++;
now=v1;
}
else{
na--;
nb++;
now=v2;
}
ans^=now;
}
printf("%lld\n",ans);
}
return 0;
}