hdu6883 Coin Game 2020杭电多校第十场

http://acm.hdu.edu.cn/showproblem.php?pid=6883

由于一个机器可以选择a,a+b和2*a+b,那么其实一个机器可以拆成两个物品,a和a+b,他们任选一个或者两个都选,都是可以的,所以就不需要判断机器冲突了。

接下来就可以直接递推了,dp[i]->dp[i+1]的时候,是直接拿一个还没选的a,还是丢掉一个以前选的最小的a,拿一个当前剩下最大的a+b。

#include<bits/stdc++.h>
using namespace std;
constexpr int threshold=10000000;
int a[5000010],b[5000010];
int S1[5000010],S2[5000010];
long long dp[15000010];
unsigned long long k1,k2;
unsigned long long xorShift128Plus(){
	unsigned long long k3=k1,k4=k2;
	k1=k4;
	k3^=(k3<<23);
	k2=k3^k4^(k3>>17)^(k4>>26);
	return k2+k4;
}
void gen(int n,unsigned long long _k1,unsigned long long _k2){
	k1=_k1,k2=_k2;
	for(int i=1;i<=n;i++){
		a[i]=xorShift128Plus()%threshold+1;
		b[i]=xorShift128Plus()%threshold+1;
	}
}
int main(){
	int n,m;
	while(~scanf("%d%d%lld%lld",&n,&m,&k1,&k2)){
		gen(n,k1,k2);
		for(int i=1;i<=n;i++){
			S1[i]=a[i];
			S2[i]=a[i]+b[i];
		}
		sort(S1+1,S1+n+1);
		sort(S2+1,S2+n+1);
		for(int i=0;i<=m;i++)dp[i]=0;
		int r=n,l=n;long long tmp1,tmp2;
		dp[1]=S1[l--];
		for(int i=2;i<=m;i++){
			/*if(S2[r]+dp[i-2]>S1[l]+dp[i-1])dp[i]=S2[r--]+dp[i-2];
			else dp[i]=S1[l--]+dp[i-1];
			*/
			if(i>3*n)
			{
				dp[i]=dp[i-1];
				continue;
			}
			tmp1=0;
			if(l>=1)
				tmp1=dp[i-1]+S1[l];
			tmp2=0;
			if(r>=1 && l<n)
				tmp2=dp[i-1]-S1[l+1]+S2[r];
			if(tmp1>tmp2)
				dp[i]=tmp1,l--;
			else
				dp[i]=tmp2,r--,l++;
			//printf("%lld ",dp[i]);
		}
		long long ans=0;
		for(int i=1;i<=m;i++)ans^=dp[i];
		printf("%lld\n",ans);
	}
}

猜你喜欢

转载自blog.csdn.net/liufengwei1/article/details/108127641