https://www.codechef.com/problems/SEAGM

题意:

n个数(可能存在相同的数),双方轮流取数。如果在一方选取之后,所有
已选取数字的GCD变为1,则此方输。
问:
1 若双方均采取最优策略,先手是否必胜?
2 若双方随机取数,先手获胜的概率为多少?
$n,ai \le 100$


状态比较难想,核心是找到一个划分阶段的顺序:根据$GCD$划分阶段

$GCD$是只会减小不会增加的

课件上的状态是$f[i][j]$表示当前$GCD$为$i$,没选的$i$的倍数有$j$个,感觉有点奇怪...

看了一下官方题解,意识到只要记录$j$为当前已经选的有$j$个就好了,已经选的一定是$i$的倍数,这样就和其他的状态比较像了

转移还是比较好想的

$1.\ f[i][j] \rightarrow f[i][j+1]\ :\ j<mult[i]$

$2.\ f[i][j] \rightarrow f[gcd(i,k)][j+1]\ :\ 1 \le gcd(i,k) \le i$

记忆化搜索倒推就行了

PS:给$gcd$加上记忆化之后$0s$就跑过去了....

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <cstring>
  4. #include <algorithm>
  5. #include <cmath>
  6. using namespace std;
  7. typedef long long ll;
  8. const int N=;
  9. const double eps=1e-;
  10. inline int read(){
  11. char c=getchar();int x=,f=;
  12. while(c<''||c>''){if(c=='-')f=-;c=getchar();}
  13. while(c>=''&&c<=''){x=x*+c-'';c=getchar();}
  14. return x*f;
  15. }
  16. int n,a[N];
  17. int g[N][N];
  18. int gcd(int a,int b){return g[a][b] ? g[a][b] : g[a][b]=(b==?a:gcd(b,a%b));}
  19. //int gcd(int a,int b){return b==0?a:gcd(b,a%b);}
  20. int f[N][N];
  21. double p[N][N];
  22. bool dfsWin(int u,int c){//printf("dfsWin %d %d\n",u,c);
  23. int &re=f[u][c];
  24. if(c==n) re=;//has chosen all
  25. if(u==) re=;//win
  26. if(re!=-) return re;
  27.  
  28. re=;
  29. int mult=;
  30. for(int i=;i<=n;i++) if(gcd(u,a[i])==u) mult++;
  31. if(c<mult&&!dfsWin(u,c+)) re=;
  32. else{
  33. for(int i=;i<=n;i++)
  34. if(gcd(u,a[i])>&&gcd(u,a[i])!=u)
  35. if(!dfsWin(gcd(u,a[i]),c+)) {re=;break;}
  36. }
  37. return re;
  38. }
  39. double dfsPro(int u,int c){//printf("dfsPro %d %d\n",u,c);
  40. double &re=p[u][c];
  41. if(c==n) re=0.0;
  42. if(u==) re=1.0;
  43. if(re>-0.9) return re;
  44.  
  45. re=0.0;
  46. int mult=;
  47. for(int i=;i<=n;i++) if(gcd(u,a[i])==u) mult++;
  48. if(c<mult) re+= (double)(mult-c) / (n-c) * (-dfsPro(u,c+));
  49. for(int i=;i<=n;i++)
  50. if(gcd(u,a[i])>&&gcd(u,a[i])!=u)
  51. re+=(double) / (n-c) *(-dfsPro(gcd(u,a[i]),c+));
  52. if(abs(re)<eps) re=;
  53. return re;
  54. }
  55. int main(){
  56. freopen("in","r",stdin);
  57. int T=read();
  58. while(T--){
  59. n=read(); int g=;
  60. for(int i=;i<=n;i++) a[i]=read(),g=gcd(a[i],g);
  61. if(g>){printf("%d %.4lf\n",n&,double(n&));continue;}
  62.  
  63. for(int i=;i<N;i++) for(int j=;j<N;j++) f[i][j]=-,p[i][j]=-1.0;
  64. int flag=dfsWin(,);
  65. printf("%d ",flag);
  66.  
  67. double prob=dfsPro(,);
  68. printf("%.4lf\n",prob);
  69. }
  70. }

CodeChef Sereja and Game [DP 概率 博弈论]的更多相关文章

  1. ●CodeChef Sereja and Game

    题链: https://www.codechef.com/problems/SEAGM题解: 概率dp,博弈论 详细题解:http://www.cnblogs.com/candy99/p/650434 ...

  2. UVA 11427 Expect the Expected(DP+概率)

    链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=35396 [思路] DP+概率 见白书. [代码] #include&l ...

  3. tyvj P1864 [Poetize I]守卫者的挑战(DP+概率)

    P1864 [Poetize I]守卫者的挑战 时间: 1000ms / 空间: 131072KiB / Java类名: Main 描述 打开了黑魔法师Vani的大门,队员们在迷宫般的路上漫无目的地搜 ...

  4. [LnOI2019]加特林轮盘赌(DP,概率期望)

    [LnOI2019]加特林轮盘赌(DP,概率期望) 题目链接 题解: 首先特判掉\(p=0/1\)的情况... 先考虑如果\(k=1\)怎么做到\(n^2\)的时间复杂度 设\(f[i]\)表示有\( ...

  5. poj 2096 Collecting Bugs(期望 dp 概率 推导 分类讨论)

    Description Ivan is fond of collecting. Unlike other people who collect post stamps, coins or other ...

  6. BZOJ 3566: [SHOI2014]概率充电器 [树形DP 概率]

    3566: [SHOI2014]概率充电器 题意:一棵树,每个点\(q[i]\)的概率直接充电,每条边\(p[i]\)的概率导电,电可以沿边传递使其他点间接充电.求进入充电状态的点期望个数 糖教题解传 ...

  7. BZOJ 1415: [Noi2005]聪聪和可可 [DP 概率]

    传送门 题意:小兔子乖乖~~~ 题意·真:无向图吗,聪抓可,每个时间聪先走可后走,聪一次可以走两步,朝着里可最近且点编号最小的方向:可一次只一步,等概率走向相邻的点或不走 求聪抓住可的期望时间 和游走 ...

  8. Codeforces1097D. Makoto and a Blackboard(数论+dp+概率期望)

    题目链接:传送门 题目大意: 给出一个整数n写在黑板上,每次操作会将黑板上的数(初始值为n)等概率随机替换成它的因子. 问k次操作之后,留在黑板上的数的期望. 要求结果对109+7取模,若结果不是整数 ...

  9. Codeforces 425E Sereja and Sets dp

    Sereja and Sets 我们先考虑对于一堆线段我们怎么求最大的不相交的线段数量. 我们先按 r 排序, 然后能选就选. 所以我们能想到我们用$dp[ i ][ j ]$表示已经选了 i 个线段 ...

随机推荐

  1. Java技术分享:如何编写servlet程序

    身为计算机专业的我,从接触java至今,已经有七年之久,从最开始的小白到现在的大白,这是一个漫长而曲折的历程. 大学刚接触Java这个学科时,一点儿都不理解java是要干嘛的,只知道学起来肯定不容易, ...

  2. phpstudy 虚拟主机域名配置注意问题

    第一步:hosts文件中添加对应:127.0.0.1+空格+你的域名 第二部:在D:\phpStudy \Apache\conf\vhosts.conf中禁用470行 第三部:配置域名和引入程序地址

  3. 怎么从一台电脑的浏览器输入地址访问另一台电脑服务器(WAMP服务器已搭建,PHPSTORM装好了)

    服务器电脑WAMP环境搭建好了,浏览器输入LOCALHOST就能访问本地 WAMP/WWW 目录下PHP文件,怎么样才能从另一台电脑通过浏览器访问呢?求详细步骤... glwbdtb | 浏览 180 ...

  4. Python3 的分支与循环

    1:条件分支 if 条件 : 语句 else: 语句 2.缩写 else: if : 可以简写为 elif ,因此Python 可以有效的避免"悬挂else" 举例: #悬挂els ...

  5. Oracle问题之字符集问题,登陆sqlplus出现问号

    退出sql SET NLS_LANG=AMERICAN_AMERICA.ZHS16GBK show parameter nls_la

  6. volatile特性及内存语义

    1.volatile变量自身具有下列特性:·可见性:对一个volatile变量的读,总是能看到(任意线程)对这个volatile变量最后的写入.·原子性:对任意单个volatile变量的读/写具有原子 ...

  7. cocos2dx 从2.2.6 到3.16 升级流水记录

    一个cocos2dx项目从2.2.6 升级至3.16 的过程,由于没有直升工具,类库升级也变动很大,有一部分需要手工完工升级.此记录供参考 1. 没有采用项目直升方式,先新建一个3.16的项目,然后把 ...

  8. java URL和URLConnection

    */ .hljs { display: block; overflow-x: auto; padding: 0.5em; color: #333; background: #f8f8f8; } .hl ...

  9. java数组基础

    */ .hljs { display: block; overflow-x: auto; padding: 0.5em; color: #333; background: #f8f8f8; } .hl ...

  10. 5分钟编写运行一个RChain合约

    今天介绍如何编写和测试一个RChain智能合约,Rholang的语法介绍在https://developer.rchain.coop/tutorial 1.安装docker 这个自己百度一下,安装都是 ...