首页 > 其他分享 >盖世计划-0724-B班模拟 C. 游戏 (game)

盖世计划-0724-B班模拟 C. 游戏 (game)

时间:2024-07-25 20:40:08浏览次数:9  
标签:std le 0724 int Alice game 盖世 物品 cur

首先,Alice 先去 \(n\) 个商店中购买物品。其中第 \(i\) 个商店售卖编号为 \(i\) 的物品,且每个物品的售价为 \(a_i\)。Alice 的总花费不能超过 \(k\)。

接着,Bob 再去另外 \(m\) 个商店中购买物品。其中第 \(i\) 个商店售卖编号为 \(n+i\) 的物品,且每个物品的售价为 \(1\)。Bob 的总花费不能超过 \(m\)。

然后,Alice 和 Bob 将他们买到的物品放在一起。然后从 Alice 开始,他们轮流进行如下操作:

  • 从剩余的物品中取走若干个物品(至少一个),取走的物品必须编号相同。

最后无法操作的人输。问 Alice 最初有多少种购买方式,使得 Alice 在后续的游戏中有必胜策略。Alice 的两种购买方式不同当且仅当两种方案中 Alice 在某一个商店中购买的物品的数量不同。答案对 \(10^9+7\) 取模。

\(1\le n,a_i\le 100\),\(0\le k\le m\le 10^{18}\)。

一看,这游戏不就是 nim 游戏嘛,有结论:

设有 \(n\) 堆石子,第 \(i\) 堆石子数量为 \(a_i\),当且仅当 \(\bigoplus\limits_{i=1}a_i\) 不为 \(0\) 时先手必胜。

分析题目的限制,第一个限制可以写成 \(\sum a_ic_i\le k\),第二个限制是啥。

我们假如 Alice 取出的石子为 \(c_1...c_L\),记 \(s=\bigoplus\limits_{i=1}c_i\),那么当 \(s\le m\) 的时候,显然 Bob 可以取遍 \([1,m]\) 中的任何数,于是就输了。

所以分析完,限制就是 \(s\ge m\)。我们要求的方案满足:

  1. \(s_1=\sum\limits_{i=1}^L a_ic_i\le k\)
  2. \(s_2=\bigoplus\limits_{i=1}^Lc_i>m\)

一看新题,又不会了。\(k\) 和 \(m\) 都特别大。我们应该想到数位 dp,它也许可以计算出方案数。考虑按位考虑 \(c_i\) 二进制上的每一位,像列竖式计算一样,这样一列上每一位都是为 \(0\) 或 \(1\) 的值。 按位枚举需要新考虑的问题,一般列入状态中转移:

  1. 进位
  2. 与上界的大小关系情况

第一个限制就变成 01 背包问题了,我们对这一位求背包就可以在 \(O(n\sum a_i)\) 的时间内计算出进位的问题。

第二个限制关心的实际上就是背包取数的数量奇偶性吧,所以背包的状态加一位表示目前取物数量的奇偶性即可。

设 \(f_{i,j,0/1,0/1}\) 表示考虑了低 \(i\) 位,最终向 \(i+1\) 位的进位为 \(j\),\(s_1\) 低 \(i\) 位与 \(k\) 低 \(i\) 位的大小关系为 \(0/1\),\(s_2\) 低 \(i\) 位与 \(k\) 低 \(i\) 位的大小关系为 \(0/1\) 的方案数。显然 \(i\) 一维可以滚动。

这里的枚举顺序为从低位到高位,与数位 dp 不同,有时这样的状态更加方便。

时间复杂度为 \(O(n\log V\sum a_i)\)。难题啊,对着 std 才勉强看懂的。

#include <bits/stdc++.h>
#define pii std::pair<int, int>
#define mk std::make_pair
#define fi first
#define se second
#define pb push_back

using i64 = long long;
using ull = unsigned long long;
const i64 iinf = 0x3f3f3f3f, linf = 0x3f3f3f3f3f3f3f3f;
/*

*/
const int N = 110, mod = 1e9 + 7; 
int n;
int a[N], s;
i64 k, m;
i64 f[2][N * N][2][2], g[N * N * 2][2];
bool comp(int x, int y, int z) {
	if(x > y) return 1;
	if(x == y && z) return 1;
	return 0; //比较数组
}
int main() {
	freopen("game.in", "r", stdin);
	freopen("game.out", "w", stdout);

    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    
	std::cin >> n >> k >> m;

	for(int i = 1; i <= n; i++) {
		std::cin >> a[i];
		s += a[i];
	}

	int cur = 1, lst = 0; //滚动数组
	f[cur][0][0][0] = 1; //初始化
	for(int b = 0; b < 60; b++) { //按位 dp
		std::swap(cur, lst); 
		for(int kl = 0; kl < 2; kl++) { //枚举先前与 k 的大小关系
			for(int ml = 0; ml < 2; ml++) { //枚举先前与 m 的大小关系
				for(int i = 0; i <= s; i++) g[i][0] = f[lst][i][kl][ml], f[lst][i][kl][ml] = 0; //背包初始化,继承先前的进位贡献
 				int nws = s; //先前的进位上界
				for(int i = 1; i <= n; i++) {
					nws += a[i]; 
					for(int j = nws; j >= 0; j--) {
						for(int k = 0; k < 2; k++) { //枚举取的数量的奇偶性 
							if(g[j - a[i]][k ^ 1] && j - a[i] >= 0) g[j][k] = (g[j][k] + g[j - a[i]][k ^ 1]) % mod; //背包
						}
					}
				}

				for(int i = 0; i <= (s << 1); i++) { //枚举进位,注意是两倍,形如 1+1/2+1/4+1/8...<=2
					for(int j = 0; j < 2; j++) { //枚举异或后这一位是 0/1
						int x = comp(i & 1, ((k >> b) & 1), kl), y = comp(j, ((m >> b) & 1), ml); //判断大小
						f[cur][i >> 1][x][y] = (f[cur][i >> 1][x][y] + g[i][j]) % mod; //转移,到下一位时进位/2
						g[i][j] = 0; //清空
					}
				}
			}
		}
	}

	std::cout << f[cur][0][0][1] << "\n"; //答案,表示进位为 0,sum(ac)<=k且xorsum(c)>m的方案数

	return 0;
}

标签:std,le,0724,int,Alice,game,盖世,物品,cur
From: https://www.cnblogs.com/FireRaku/p/18324100

相关文章

  • 20240724模拟赛订正题笔记
    (T1)lnsyoj2208逆流而上/P10737[SEERC2020]ReverseGame考虑到失败时字符串应为前面都是0,后面都是1(例如"0000001111111")所以可以将原串的逆序对数求出,记为m,对于每个可翻转的串进行分类讨论:1."10"->"01"可以将原串的逆序对减1。2."100"->"001""110"->"011......
  • 如何在 Brawl Stars 中使用 game.brawlstarsgame.com 主机和 9339 端口?
    需要使用套接字连接:主机:game.brawlstarsgame.com端口:9339主机可以接受什么参数、以什么形式?我的主要目标是为大量帐户创建一个自动注册器。我理解你想创建一个BrawlStars帐户的自动注册器,并希望利用你提供的game.brawlstarsgame.com主机和9339端口的信息。......
  • [lnsyoj2208/luoguP10737]Reverse Game
    来源原题链接2024.7.25校内测验T1题意给定01串,每次可将其中的10、100、110、1010翻转,无法操作的一方输,求哪方必胜赛时DFS0ptssol可以发现,10减少\(1\)个逆序对,其余都可减少\(2\)个逆序对;同时,当串内存在逆序对时,一定可以翻转(因为一定存在10),因此,我们可以计算串内......
  • YC322A [ 20240724 CQYC NOIP 模拟赛 T4 ] 庫的 序计数(counting)
    题意给定一棵树\(T\),每次操作在某个点下方接上\(k\)个儿子。询问期望多少次排列,使得\(a_{fa_i}<a_i\)。保证\(k\)是偶数,对\(65536\)取模。\(n\le10^5,k\le2\times10^9\)。Sol考虑假如已经确定了一棵树的形态,如何求出最终的答案?可以发现对于每一个节点......
  • 20240724总结
    上午模拟赛100+50+0+0.T3本来能拿更高的分数,但是预处理放到里面了。T1\((kruskal+lca)\)最小瓶颈生成树/最短路。其实仔细想想,让他们之间最大边最短,其实就是最短的代价连通。据此得到解决。T2构造序列a:\[i\&1:a[i]=i+1/2\]\[i\%2==0:a[i]=n+1-i/2\]现......
  • Java后端开发知识点积累20240724
    1.使用流(Stream)API和lambda表达式来从一个dateBaseList列表中提取所有的title字段,并将这些title值收集到一个新的列表中dateBaseList.stream().map(InspectionManageEntity::getTitle).collect(Collectors.toList());2.@PathVariable注解作用@PathVariable是Spring框架中的......
  • 坐牢第十六天 20240724
    笔记1.二叉树的补充1.1二叉树的创建shu.h​​​​​​​​​​#ifndefSHU_H#defineSHU_H#include<myhead.h>typedefchardatatype;//定义节点类型typedefstructNode{datatypedata;//数据域structNode*L;//左孩子指针structNode*R;//右孩子指......
  • 20240724【省选】模拟
    挂了四分,掉了一名,不过这也说明我的实力就只有这点,根本不够,果然以后还是直接【数据删除】得了。T1其实就是个树剖,每个点维护左右子树的最大深度以及左右子树内的最大答案,然后就…………没了?淦,也是实现问题,应该想到的。然后就是修改边权是改成\(w-a_p\),\(a_i\)是记录下来的\(i......
  • C. Card Game
    原题链接题解性质:取奇数位置相加,取偶数位置不相加经过若干次实验,可以得到删除第\(i\)个数,对\([1,i-1]\)个数的奇偶性不造成影响因此,我们试着从最末尾开始删(无后效性)如果末尾是负数,不用管如果末尾是正数,如果是奇数位置,直接相加如果末尾是正数,如果是偶数位置,如果......
  • 学习pcie—20240724
    因为前一段时间看了xdma的IP核手册,发现只看xdma看不太懂,不清楚pcie的传输的流程,不了解报文格式,所以看看pcie手册,主要关注发送接收时序首先是pcieIP核与xdmaIP核的区别:IntegratedBlockforPCIExpress:7SeriesIntegratedBlockforPCIExpress是最基础的PCIeIP,实现的是......