列表

详情


NC230367. HearthStone!

描述

lyyxym都是炉石传说的痴迷者。这天,两人终于学完了ACM的所有知识,他们决定开一把两人对战来放松一下。

我们简化模型,规定:每个人的场上都有怪物,怪物有三个属性:攻击力x,生命值y,亡语召唤zx表示该怪物与另一个怪物碰撞时,对对方造成的伤害;当一次碰撞结束后,该怪物的生命值则怪物死亡;怪物死亡时,若,则会在该怪物死亡后立刻召唤z的怪物。

注意:

1.每个人场上的怪物数量有上限
2.一次碰撞是相互的,即双方的怪物会同时受到来自对方的伤害。

例:

怪物数量上限为3lyy场上有两个的怪物,xym场上有两个的怪物,lyy的一个怪物与xym的一个怪物碰撞碰撞后两个怪物都死亡,由于lyy的怪物,所以当它死亡后,会召唤两个的怪物,此时lyy场上一共有一个的怪物,两个的怪物;同理,xym的怪物,它应该召唤3的怪物,但是由于怪物数量上限为3,所以只成功召唤两个的怪物,此时xym场一共有一个的怪物,两个的怪物。

决胜局中,怪物数量上限为limitlyy场上只有血量无限的一个怪物,该怪物不能主动攻击,其x,y由输入决定;xym场上有n种怪物,每种怪物的,其z由输入决定。

xym知道他的怪物虽然有很多,但是无论如何也打不死lyy的怪物。xym想知道,他的怪物们全部攻击一次之后(亡语召唤出来的怪物也有一次攻击次数),lyy场上的怪物的剩余血量有多少种可能(若剩余246血即有3种)。

输入描述

第一行一个整数T,表示有T组数据

每组数据:第一行输入四个整数limit,n,x,y,分别表示:怪物数量上限、xym场上的怪物种数、lyy场上的怪物的数据。

接下来n行,第i行两个个整数z_i, num_i,表示xym场上第i种怪物的z值,第i种怪物的数量。

输出描述

每组数据:输出一个整数sum,表示lyy场上的怪物的剩余血量的可能总数。

示例1

输入:

2
4 2 1 100
1 2
2 2
4 2 1 100
0 2
10 2

输出:

3
6

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++(g++ 7.5.0) 解法, 执行用时: 695ms, 内存消耗: 16052K, 提交时间: 2023-01-05 11:04:26

#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;

ll limit, n, x, y, sum = 0;

//随从
struct gf {
	ll num, z;
}a[1000010];

bool cmp1(gf a, gf b) {
	return a.z < b.z;
}

int main() {
	int T;
	cin >> T;
	while (T--) {
		cin >> limit >> n >> x >> y;
		for (int i = 1; i <= n; i++) {
			cin >> a[i].z >> a[i].num;
			sum += a[i].num;
		}
		//0攻嘲讽
		if (x == 0)
		{
			cout << 1 << endl;
			continue;
		}
		//按亡语进行排列
		sort(a + 1, a + 1 + n, cmp1);
		ll max = y, min = y;
		//剩余格子数
		ll spare = limit - sum;
		ll sumnow = sum;
		for (int i = 1; i <= n; i++) {
			//血量最大情况:先把所有亡语撞开,让1-1最少
			if (a[i].z == 0) continue;
			max -= a[i].num;
			if (limit >= sumnow + (a[i].z - 1) * a[i].num)
			sumnow += (a[i].z - 1) * a[i].num;
			else 
			sumnow = limit;
		}
		max -= sumnow;
		for (int i = 1; i <= n; i++) {
			if (a[i].z + sum - 1 > limit)
			{
				long long int d = sum + a[i].z - 1 - limit;
				if (a[i].num >= d)
				{
					min = min - d * (limit - sum + 1 + limit - sum + d) / 2 - d;
					min = min - (a[i].num - d) * (a[i].z + 1);
				}
				else
				{
					min = min - a[i].num * (limit - sum + 1 + limit - sum + a[i].num) / 2 - a[i].num;
				}
			}
			else
				//每一种怪的第一个撞开亡语全容纳
				min = min - a[i].num * (a[i].z + 1);
			    sum -= a[i].num;
		}
		cout << max - min + 1 << endl;
	}
}

C++ 解法, 执行用时: 898ms, 内存消耗: 16040K, 提交时间: 2021-11-27 13:36:09

#include<bits/stdc++.h>
using namespace std;
long long limit,T,n,x,y,hit,k,maxd,mind,cnt;
struct S
{
	long long z,num;
}a[1000000];
bool cmp(S x,S y)
{
	return x.z<y.z;
}
int main()
{
	int i;
	cin>>T;
	while(T--)
	{
		k=maxd=mind=cnt=0;
		cin>>limit>>n>>x>>y;
		if(x)
		{
			for(i=0;i<n;i++)
			{
				cin>>a[i].z>>a[i].num; k+=a[i].num; 
				if(a[i].z) mind+=a[i].z*a[i].num;
				else cnt+=a[i].num;
			}
			sort(a,a+n,cmp);
			mind=k+min(limit-cnt,mind); 
			for(i=0;i<n;i++)
	 	    {
				if(k-1+a[i].z<=limit) maxd+=(a[i].z+1)*a[i].num;
				else if(a[i].z+k-a[i].num>limit) maxd+=(2*limit-2*k+a[i].num+3)*a[i].num/2;
				else maxd+=(a[i].z+k-limit)*(limit+a[i].z-k+1)/2+a[i].num+a[i].z*(a[i].num-a[i].z+limit-k);
				k-=a[i].num;
			}
			cout<<maxd-mind+1<<endl;
		}
		else 
		{
			for(i=0;i<n;i++)  cin>>a[i].z>>a[i].num;
            cout<<1<<endl; 
		} 
	}
	return 0;
} 

上一题