最新消息: USBMI致力于为网友们分享Windows、安卓、IOS等主流手机系统相关的资讯以及评测、同时提供相关教程、应用、软件下载等服务。

箱子

IT圈 admin 21浏览 0评论

箱子

题目描述

小猪佩奇和其他n-1个小伙伴们正在玩一个老套的游戏。
一个房间中,有n个随机打乱过的箱子放成一排,每个箱子里有一张纸条,写着一个人的名字。每个人要按一定顺序走进房间,打开最多k个箱子,如果其中没有自己的名字游戏就失败了。每个人走出房间的时候需要关上箱子。(游戏中箱子的顺序不会再被调换)游戏前他们可以商量出一个策略,但是游戏开始之后他们不能互相交流。
小猪佩奇想知道最优策略下游戏成功,即每个人都找到写有自己名字的箱子的概率。

注:一个人每次打开箱子并非同时开启,而是依次打开。

做法

我们来考虑策略。
第i个人策略是这样的,打开i,如果a[i]!=i,打开a[i],如果a[a[i]]!=i,打开a[a[i]]……依次类推。
那么显然成功的概率就是排列形成的每个环大小都不超过k。
我们来证明这是最优策略。
考虑一个简单问题,每个人进去开了箱子就不闭上了。显然新问题获胜概率大于等于原问题。
在这个简单问题里,每个箱子都要开一次。每个人进去只会开没开的箱子,这些箱子不管哪个都是一样的,因此相当于随机开箱。
对于一种开箱方法,即一个人如果开出了数字s1~st(t<=k),我们可以构造p[s1]=s2,p[s2]=s3……p[st]=s1。
那么每种开箱方法对应了一个排列,这个排列形成的每个环大小都不超过k。
因此新问题的获胜概率就是排列形成的每个环大小都不超过k。这样我们也就证明了原问题的这个策略最优。
然后DP就很简单了。

#include<cstdio>
#include<algorithm>
#define fo(i,a,b) for(i=a;i<=b;i++)
using namespace std;
typedef long long ll;
const int maxn=200000+10,mo=998244353;
int ni[maxn],p[maxn];
int i,j,k,l,t,n,m,ca,ans;
int qsm(int x,int y){if (!y) return 1;int t=qsm(x,y/2);t=(ll)t*t%mo;if (y%2) t=(ll)t*x%mo;return t;
}
int main(){freopen("box.in","r",stdin);freopen("box.out","w",stdout);fo(i,1,200000) ni[i]=qsm(i,mo-2);scanf("%d",&ca);while (ca--){scanf("%d%d",&n,&k);p[0]=1;fo(i,1,n){p[i]=p[i-1];if (i-k-1>=0) (p[i]-=p[i-k-1])%=mo;p[i]=(ll)p[i]*ni[i]%mo;(p[i]+=p[i-1])%=mo;}ans=(p[n]-p[n-1])%mo;(ans+=mo)%=mo;printf("%d\n",ans);}
}

箱子

题目描述

小猪佩奇和其他n-1个小伙伴们正在玩一个老套的游戏。
一个房间中,有n个随机打乱过的箱子放成一排,每个箱子里有一张纸条,写着一个人的名字。每个人要按一定顺序走进房间,打开最多k个箱子,如果其中没有自己的名字游戏就失败了。每个人走出房间的时候需要关上箱子。(游戏中箱子的顺序不会再被调换)游戏前他们可以商量出一个策略,但是游戏开始之后他们不能互相交流。
小猪佩奇想知道最优策略下游戏成功,即每个人都找到写有自己名字的箱子的概率。

注:一个人每次打开箱子并非同时开启,而是依次打开。

做法

我们来考虑策略。
第i个人策略是这样的,打开i,如果a[i]!=i,打开a[i],如果a[a[i]]!=i,打开a[a[i]]……依次类推。
那么显然成功的概率就是排列形成的每个环大小都不超过k。
我们来证明这是最优策略。
考虑一个简单问题,每个人进去开了箱子就不闭上了。显然新问题获胜概率大于等于原问题。
在这个简单问题里,每个箱子都要开一次。每个人进去只会开没开的箱子,这些箱子不管哪个都是一样的,因此相当于随机开箱。
对于一种开箱方法,即一个人如果开出了数字s1~st(t<=k),我们可以构造p[s1]=s2,p[s2]=s3……p[st]=s1。
那么每种开箱方法对应了一个排列,这个排列形成的每个环大小都不超过k。
因此新问题的获胜概率就是排列形成的每个环大小都不超过k。这样我们也就证明了原问题的这个策略最优。
然后DP就很简单了。

#include<cstdio>
#include<algorithm>
#define fo(i,a,b) for(i=a;i<=b;i++)
using namespace std;
typedef long long ll;
const int maxn=200000+10,mo=998244353;
int ni[maxn],p[maxn];
int i,j,k,l,t,n,m,ca,ans;
int qsm(int x,int y){if (!y) return 1;int t=qsm(x,y/2);t=(ll)t*t%mo;if (y%2) t=(ll)t*x%mo;return t;
}
int main(){freopen("box.in","r",stdin);freopen("box.out","w",stdout);fo(i,1,200000) ni[i]=qsm(i,mo-2);scanf("%d",&ca);while (ca--){scanf("%d%d",&n,&k);p[0]=1;fo(i,1,n){p[i]=p[i-1];if (i-k-1>=0) (p[i]-=p[i-k-1])%=mo;p[i]=(ll)p[i]*ni[i]%mo;(p[i]+=p[i-1])%=mo;}ans=(p[n]-p[n-1])%mo;(ans+=mo)%=mo;printf("%d\n",ans);}
}
发布评论

评论列表 (0)

  1. 暂无评论