传送门

其实没有那么复杂

发现如果先选择数字xxx,再选择数字yyy和

先选择数字yyy,再选择数字xxx没有区别,造成的影响是一样的

所以定义f[1<<20]f[1<<20]f[1<<20]为状态下的期望步数

若二进制第iii位是111说明被选择过了

那么现在就是快速求出每个状态是否合法

那么对于f[i]f[i]f[i]而言,枚举每一位二进制变成新的状态

f[i]=1+1n∗(f[a1]+f[a2]+f[a3]....+num∗f[i])f[i]=1+\frac{1}{n}*(f[a_1]+f[a_2]+f[a_3]....+num*f[i])f[i]=1+n1​∗(f[a1​]+f[a2​]+f[a3​]....+num∗f[i])

那么可以解得f[i]f[i]f[i]

如果f[i]f[i]f[i]本身本来就合法,就不需要这样转移,直接f[i]=0f[i]=0f[i]=0

合法不合法可以暴力预处理出来

#include <bits/stdc++.h>
using namespace std;
#define int long long
const int maxn = 2e5+10;
const int mod = 998244353;
int a[22],b[22],c[22],n,ok[1<<21],f[1<<21];
void change(int index)
{int l=1,r=index+1;c[index] = index;for(int i=1;i<=n;i++)if( b[i]<index ) c[l++] = b[i];else if( b[i]>index )   c[r++] = b[i];for(int i=1;i<=n;i++)   b[i] = c[i];
}
bool isok(int x)
{for(int i=1;i<=n;i++)   b[i] = a[i];for(int i=0;i<n;i++){if( (x&(1<<i))==0 ) continue;change(i+1);  }for(int i=1;i<=n;i++)if( b[i]!=i ) return false;return true;
}
int quick(int x,int n)
{int ans = 1;for( ; n ; n>>=1,x=x*x%mod )if( n&1 ) ans = ans*x%mod;return ans;
}
signed main()
{cin >> n;for(int i=1;i<=n;i++)    cin >> a[i];int maxx = (1<<n)-1, p = quick(n,mod-2);for(int i=0;i<=maxx;i++)   ok[i] = isok(i);for(int i=maxx;i>=0;i--){if( ok[i] )  continue;int num = 0;for(int j=0;j<n;j++){int nxt = i|(1<<j);if( nxt==i )   num++;else    f[i] = ( f[i]+p*f[nxt]%mod )%mod;}f[i] = ( f[i]+1 )*n%mod*quick( n-num,mod-2 )%mod;}cout << f[0];
}

预处理那部分如果写成递归版本会快很多,相当于启发式合并那样不需要每次从头来过

dfs代码

官方题解另一种版本

这就更暴力了

直接把aaa序列作为状态,定义f[a]f[a]f[a]为状态为aaa时还需要的期望

所以这个fff是mapmapmap,aaa是个vectorvectorvector

那么枚举每一个数字作为本次随机选择的数字,转移是

f[a]=1+1n∗(f[a1]+f[a2]+f[a3]....+num∗f[a])f[a]=1+\frac{1}{n}*(f[a_1]+f[a_2]+f[a_3]....+num*f[a])f[a]=1+n1​∗(f[a1​]+f[a2​]+f[a3​]....+num∗f[a])

这样可以求得f[a]f[a]f[a]

记忆化搜索去解,思想差不多

#include <bits/stdc++.h>
using namespace std;
#define int long long
const int maxn = 2e5+10;
const int mod = 998244353;
int vis[22],n,p;
map<vector<int>,int>f;
int quick(int x,int n)
{int ans = 1;for( ; n ; n>>=1,x=x*x%mod )if( n&1 ) ans = ans*x%mod;return ans;
}
int dfs(vector<int> a)
{if( f[a] ) return f[a];vector<int>b; b.resize(n);int num = 0;for(int i=0;i<n;i++){if( vis[i] )    { num++; continue; }int l=-1,r=i; b[i] = i;for(int j=0;j<n;j++)if( a[j]<i )   b[++l] = a[j];else if( a[j]>i )   b[++r] = a[j];vis[i] = 1;//已经改变过这个点了 if( a==b )   num++;else    f[a] = ( f[a]+dfs(b)*p%mod )%mod;vis[i] = 0;//回溯 }   return f[a] = ( 1+f[a] )*n%mod*quick( n-num,mod-2 )%mod;
}
vector<int>a;
signed main()
{cin >> n; a.resize(n);for(int i=0;i<n;i++){scanf("%lld",&a[i] );a[i]--;}p = quick(n,mod-2);cout << dfs(a);
}

牛客练习赛31 C.无畏死灵术士莉莲娜与锁链面纱(期望dp)相关推荐

  1. 牛客练习赛31 C 无畏死灵术士莉莲娜与锁链面纱(dfs + 期望dp)

    太久没有做期望/概率dp,已锈... 大概就是说给你一个1到n的全排列,然后每次随机选择一个数字在不改变其他数字相对位置的前提下,把比他小的数字放在他前面,大的在后面.问期望几次能够使得这个序列有序. ...

  2. 牛客练习赛31 B 赞迪卡之声妮莎与奥札奇(逻辑+博弈) B

    链接:https://ac.nowcoder.com/acm/contest/218/B 来源:牛客网 赞迪卡之声妮莎与奥札奇 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 2621 ...

  3. 牛客练习赛31: D. 神器大师泰兹瑞与威穆(链表)

    链接:https://ac.nowcoder.com/acm/contest/218/D 来源:牛客网 题目描述 「只要我拉动绳线,你就得随之起舞.」          --泰兹瑞 泰兹瑞来到卡拉德许 ...

  4. 牛客练习赛46 C 华华跟奕奕玩游戏 (期望,概率)(详解)

    链接:https://ac.nowcoder.com/acm/contest/894/C 来源:牛客网 华华跟奕奕玩游戏 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 524288K ...

  5. 牛客练习赛81 E. 小 Q 与函数求和 1( “简单莫比乌斯反演” ,欧拉函数性质)

    整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 牛客练习赛81 E. 小 Q 与函数求和 1( "简单莫比乌斯反演" ) Prob ...

  6. 解题报告(一)C、(牛客练习赛41 F)简单数学题(数论 + FWT)(3.5)

    繁凡出品的全新系列:解题报告系列 -- 超高质量算法题单,配套我写的超高质量题解和代码,题目难度不一定按照题号排序,我会在每道题后面加上题目难度指数(1∼51 \sim 51∼5),以模板题难度 11 ...

  7. 牛客练习赛34 E little w and Digital Root(数位dp)

    title: 牛客练习赛34 E little w and Digital Root(数位dp) date: 2018-12-17 22:38:37 tags: 数位dp categories:ACM ...

  8. 牛客练习赛34 - C little w and Segment Coverage(思维、树状数组)

    title: 牛客练习赛34 - C little w and Segment Coverage(思维.树状数组) date: 2018-12-15 16:36:55 tags: [树状数组,思维] ...

  9. 牛客练习赛52 | C | [烹饪] (DP,裴蜀定理,gcd)

    牛客练习赛52 C 烹饪 链接:https://ac.nowcoder.com/acm/contest/1084/C来源:牛客网 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 327 ...

最新文章

  1. java学习规划-转的
  2. win10内核linux,windows 10中发布完整的Linux内核
  3. php随机获取文件夹,php从文件夹随机读取文件的方法
  4. 【2D动画】《想你》。。。。难以想象
  5. nao机器人行走速度_震撼!寒冬腊月里惊现多台历途外墙清洗机器人
  6. JavaScript (If...Else和Switch和循环遍历) 语句以及常用消息框
  7. Shell脚本编程之(二)简单的Shell脚本练习
  8. Eclipse注释快捷键、如何生成API以及可能遇到的问题解决
  9. oracle两天教程,Linux菜鸟的两天Oracle安装生活
  10. flutter 仿网易云音乐(1)
  11. 关于ccs软件的简单使用
  12. 读《因果的真相》第八、九章摘抄笔记
  13. aspose.words复制插入同一word文档中的某个页面
  14. spirng中bean对象的作用范围
  15. [OpenCV]关于opencv不能打开某些视频得问题
  16. uni-app开发的h5,使用微信授权登录(前置条件+具体代码)
  17. 关于JSON.parse(),JSON.stringify(),jQuery.parseJSON()的用法
  18. ecg信号越界_监护仪器显示ECG是什么意思
  19. 年轻人不讲武德,不好好上班,用HaaS监控“老板来了”
  20. ug8.0更改计算机名,Ug8.0电脑名改了怎么处理

热门文章

  1. python基础语言与应用第五章_Python基础教程读书笔记(第5章—第6章:条件、循环和其他语句;抽象)...
  2. 耐克NIKE验厂的两个方面总结
  3. 【自动化】浅度分析自动化行业,深度好文!
  4. GBT 19668 (1-6)整套
  5. js学习笔记-2018年7月12日
  6. 音视频开发5. ZLMediaKit库入门使用 编译安装
  7. 教你python自动识别图文验证码的解决方案!
  8. html文件剖析 - mdn学习
  9. C#——设计一个简单的窗体程序,在文本框中输入两个点的坐标值,单击“确定”按钮时显示两点之间的距离。
  10. 如何删掉“分节符(下一页)