算法思维训练之思维题和博弈论实战演练 (2月9日)

145 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 9 天,点击查看活动详情

Even-Odd Game(博弈)

image.png

题意:

Alice和Bob在数组a中的n个整数,选择数字

Alice如果选择偶数,那么将这个数字加到Alice的得分中,如果选择了奇数,则不计分

Bob如果选择奇数,那么将这个数字加到Bob的的分钟,如果选择了偶数,则不计分

两者皆采取最优策略,Alice先走,得分多者获胜,如果是平局则输出Tie。

题解:

两者都是最优策略,所谓最优策略就是,判断我方得分的最大值与对方得分的最大值的大小,如果我方得分最大值小于 对方得分的最大值,自然是先把对方的拿掉,反之先拿自己的,让自己加分。

那么让这个序列从大到小排序,Alice先拿,那么序列下标是1~n的,那么:

  • 如果是序列下标为奇数,那么就是Alice拿,如果当前数字是偶数,那么就将该数字加到得分,如果当前数字是奇数,不做任何操作。
  • 如果是序列下标为偶数,那么就是Bob拿,如果当前数字是奇数,那么就将该数字加到得分,如果当前数字是偶数,不做任何操作。
const int N = 200010;
int a[N];
signed main() {
        scanf("%d", &t);
	while (t--) {
		scanf("%d", &n);
		for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
		//从大到小排序 
		sort(a + 1, a + n + 1, cmp);
		int Alice = 0, Bob = 0;
		for (int i = 1; i <= n; i++) {
			//奇数下标 
			if (i % 2) { if (a[i] % 2 == 0) Alice += a[i];//偶数就加进去 } 
			else if (a[i] % 2) Bob += a[i];//奇数就加进去
		}
		if (Alice > Bob) printf("Alice\n");
		else if (Alice < Bob) printf("Bob\n");
		else printf("Tie\n");
	}
	return 0;
}

Nezzar and Lucky Number(思维水题)

image.png

题意:

给定一个luck number d,只要包含d的数字都算是luck number。

例如d = 7, 那么7、17、27、37、47、57、67、77 ... 都算是luck number

现在给出n个数,判断这 aia_i 能否由luck number组成;

题解:

分为两种情况:

  1. aia_i >= 10d的时候,是一定满足题意的

    比如说:当d == 7时:

    • 首先:14、21、28、35、42、49、56、63 这些个数能组成的,也满足题意
    • 80 == 17 + 63(7 × 9)
    • 81 == 14 + 67
    • 82 == 35 + 47

    所以是:

  • aia_i>10d的时现在目标数的尾数为 x 那么就是找对应 x 能由7和另外一个数得到,假设,目标数为82

  • 那么2 需要5和7拼出来,那么先在 14、21、28、35、42、49、56、63 中找到以5为个位的数字,即35,再加上幸运数字 4即刻即可拼出 82。所以同理可得,只要 aia_i > 10d的时候,是一定满足题意的。

  1. aia_i < 10d的时候:
    • 7 × 1 = 7:所以,≥7的数字且个位为7的数字满足题意
    • 7 × 2 = 14:所以,≥14的数字且个位为4的数字满足题意,例如:24 = 7 + 17,34 = 17 + 17
    • 7 × 3 = 21:所以,≥21的数字且个位为1的数字满足题意,例如:31 = 7 + 7 + 17,41 = 7 + 17 + 17
    • 7 × 4 = 28:所以,≥28的数字且个位为8的数字满足题意
    • 7 × 5 = 35:所以,≥35的数字且个位为5的数字满足题意
    • 7 × 6 = 42:所以,≥42的数字且个位为2的数字满足题意
    • 7 × 7 = 49:所以,≥49的数字且个位为9的数字满足题意
    • 7 × 8 = 56:所以,≥56的数字且个位为6的数字满足题意
    • 7 × 9 = 63:所以,≥63的数字且个位为3的数字满足题意
signed main() {
	scanf("%d", &t);
	while (t--) {
		int q, d;
                scanf("%d%d", &q, &d);
		while (q--) {
			scanf("%d", &x);
			if (x >= d * 10) {
				printf("YES\n");
				continue;
			}
			if (x % 10 == d || x / 10 == d) {
				printf("YES\n");
				continue;
			}
			int f = 0;
			//在d~10d这里枚举一遍 
			for (int i = 1; i <= 10; i++) {
				//要特判一下,如果这数字比目标数字大,那么自然不能满足题意 
				if (i * d > x) break; 
				int a = i * d % 10;//能满足的数字的个位 
				int b = x % 10;//目标数字的个位 
				if (a == b) {
					f = 1;
					break;
				}
			}
			if (f) printf("YES\n");
			else printf("NO\n"); 
		}
	}
	return 0;
}