首页 > 其他分享 >基础博弈练习题

基础博弈练习题

时间:2022-12-14 21:37:47浏览次数:36  
标签:练习题 博弈 int register 基础 long 1000001 edge return

基础博弈练习题

链接:\(https://www.luogu.com.cn/problem/P5652\)

题目描述:
规则是这样的,先给定一个正整数\(m\)和一个\(n\)个数的序列\(B\),一开始有一个棋子在\(B\)的第一个位置,并将\(B1\)减去\(1\)。此后双方轮流操作,每次操作,假设当前棋子在\(i\),可以把棋子移到一个位置\(j\),满足\(j∈[i,min(i+m,n)]\)且\(Bj>0\),然后将\(Bj\)减1,\(YSGH\)先手,谁先不能操作谁输。

众所周知,\(YSGH\)和\(YGSH\)都是绝顶聪明的,所以两人都会使用最优策略。

而隔膜使用的序列\(B\)是一个序列\(A\)的一个连续非空子序列,当然序列A和每次隔膜使用的序列\(B\)都是\(YSGS\)定的。

现在他们进行了\(q\)轮游戏,给出每轮游戏使用的区间,请你判断每轮谁会赢。

题解:可以令\(dp[i]\)表示当前i是否能赢,可以看出
当\(dp[j]\)(\(j∈[i,min(i+m,n)]\))全等于0时,\(dp[i]\)=\(i\)%\(2\)
当\(dp[j]\)(\(j∈[i,min(i+m,n)]\))有等于1时,\(dp[i]=0\)

若我们将每一个奇数点看做一个电线杆,则电线杆会覆盖\([max(i-m,1),i]\)这一段区间,则下一个\(dp[i]=1\)的点一定在所覆盖的区间前面,且是一个电线杆,我们可以将这两个点连一条边。原问题转化为,对于一个图,求\(a\)是否能到达\(b\),这个问题显然可以用倍增来求,但这样只能拿到\(90\)分。

可以发现,建出来的图一定是棵树,原问题转化为,求\(a\)是否在\(b\)的子树中。可以将整棵树的\(dfs\)序求出,查询\(a\)是否\(∈[b,b+size[b]-1]\)即可

#include<iostream>
#include<cmath>
#include<cstdio>
using namespace std;
struct node
{
	int v,nt;
};
node edge[1000001];
long long t,f[1000001],ans,a[1000001],mod,len,head[1000001],dfn[1000001],length,sz[1000001];
long long fast_pow(register long long a,register int b)
{
  if (b==0)
    return 1;
  if (b&1)
    return fast_pow(a*a,b/2)*a;
  else
    return fast_pow(a*a,b/2);
}
long long A,B,C,P;
inline long long rnd(){return A=(A*B+C)%P;}
inline void add(register int x,register int y)
{
	edge[++len].v=y;
	edge[len].nt=head[x];
	head[x]=len;
	return;
}
inline void dfs(register int x)
{
	sz[x]=1;
	dfn[x]=++length;
	for (register int i=head[x];i>0;i=edge[i].nt)
		if (!dfn[edge[i].v])
		{
			dfs(edge[i].v);
			sz[x]+=sz[edge[i].v];
		}
	return;
}
signed main()
{
  	mod=fast_pow(2,32);
  	register long long n,m,q,l,r,type;
 	cin>>n>>m>>q>>type;
  	for (register int i=1;i<=n;++i)
    {
     	scanf("%lld",&a[i]);
    	a[i]%=2;
    }
  	if (type==1)
    	cin>>A>>B>>C>>P;
  	for (register int i=1;i<=n;++i)
    {
      if (a[i]==1)
		t=i;
      f[i]=t;
    }
  	for (register int i=1;i<=n;++i)
    {
    	if (i>m+1&&a[i]==1)
        	add(f[i-m-1],i);
    	if (a[i]==0)
			add(f[i],i);
    }
    for (register int i=1;i<=n;++i)
    	if (!dfn[i])
    		dfs(i);
  	for (register int i=1;i<=q;++i)
    {
       	if (type==0)
        	cin>>l>>r;
      	else
        {
            l=rnd()%n+1;
            r=rnd()%n+1;
            if (l>r)
               swap(l,r);
        }
       	if (dfn[r]>dfn[l]+sz[l]-1||dfn[r]<dfn[l]||(l==r&&a[l]==0))
	 		ans=(ans+1ll*i*i%mod)%mod;
    }
  cout<<ans<<endl;
  return 0;
}

标签:练习题,博弈,int,register,基础,long,1000001,edge,return
From: https://www.cnblogs.com/zhouhuanyi/p/16983581.html

相关文章

  • 详解物理层-通信基础【王道计算机网络笔记】
    ![![[附件/Pastedimage20221120151810.png|100]]](https://img-blog.csdnimg.cn/6765bf898d2a41588eb9e60989ab40bf.png=x300)物理层接口特性物理层解决如何在连接各种......
  • 基础博弈练习题
    基础博弈练习题链接:$https://www.luogu.com.cn/problem/P5652$题目描述:规则是这样的,先给定一个正整数$m$和一个$n$个数的序列$B$,一开始有一个棋子在$B$的第一......
  • java 常见基础题
    Java中==和equals和hashCode的区别基本数据类型的​​==​​比较的值相等.类的​​==​​​比较的内存的地址,即是否是同一个对象,在不覆盖​​equals​​​的情况下,同比较内......
  • 【matlab基础】使用simulink同步CAN数据
    前言最近分析CAN报文数据,不同CAN通道的数据时间和size不一致,使用matlab中的simulink工具实现不同时间戳周期数据的对齐和同步。平常用得少,担心自己忘记了用的时候麻烦别人......
  • Java基础之变量
    变量变量为可以变化的量。java是一种强类型语言,每个变量都必须声明其类型。Java变量是程序中最基本的存储单位,其要素包括:变量名,变量类型和作用域。 数据类型变量名=......
  • 基础流媒体协议
    一,基本概念流媒体(streamingmedia)是指将一连串的媒体数据压缩后,经过网上分段发送数据,在网上即时传输影音以供观赏的一种技术与过程,此技术使得数据包得以像流水一样发送;如......
  • 防火墙基础之思科实验防病毒安全防护​
    防火墙基础之思科实验防病毒安全防护​原理概述:​防火墙(英语:Firewall)技术是通过有机结合各类用于安全管理与筛选的软件和硬件设备,帮助计算机网络于其内、外网之间构建一道相......
  • C++ 如果设置日期 & 时间基础篇
        ......
  • 利联科技——0基础学会了后自己都能开​​传奇游戏45.113.200​​
    ​  作为经典的怀旧游戏,传奇游戏赢得了许多人的青睐,在这个科技的时代,玩服已经满足不了了,逐渐越多数人会选择自己开服,那么开服需要准备什么呢。 按照开服流程,咱们一步一......
  • JavaScript学习--Item29 DOM基础详解
    看完JavaScript高级程序设计,整理了一下里面的DOM这一块的知识点,比较多,比较碎!DOM在整个页面的地位如图:DOM(文档对象模型)是针对HTML和XML文档的一个API(应用程序编程接口)。DOM......