Description

Zeit und Raum trennen dich und mich.
时空将你我分开。

B 君在玩一个游戏,这个游戏n个灯和n个开关组成,给定这n个灯的初始状态,下标为从1到n的正整数。

每个灯有两个状态亮和灭,我们用1来表示这个灯是亮的,用0表示这个灯是灭的,游戏的目标是使所有灯都灭掉。

但是当操作i个开关时,所有编号为i的约数(包括1和i)的灯的状态都会被改变,即从亮变成灭,或者是从灭变成亮。

B 君发现这个游戏很难,于是想到了这样的一个策略,每次等概率随机操作一个开关,直到所有灯都灭掉。

这个策略需要的操作次数很多,B 君想到这样的一个优化。如果当前局面,可以通过操作小于等于k个开关使所有灯都灭掉

那么他将不再随机,直接选择操作次数最小的操作方法(这个策略显然小于等于k步)操作这些开关。

B 君想知道按照这个策略(也就是先随机操作,最后小于等于k步,使用操作次数最小的操作方法)的操作次数的期望。

这个期望可能很大,但是 B 君发现这个期望乘n的阶乘一定是整数,所以他只需要知道这个整数对100003取模之后的结果。

1<=n<=100000,0<=k<=n。对于50%的数据,k=n。

这题也是咕了好久啊,今天难得改题快,回来把它干了。

然而我颓题解了,想了几次了也没有想出来,呃。。。颓题解再怎么样也比干脆不做好一些

这题的主要难点在于如何确定状态定义,其它的其实还好。

看那个50%的部分分(数据水了,能拿80。。。)

也就是我们先考虑最优决策是什么。

首先,你操作编号小的开关,编号大的那个灯泡不会有反应。

所以对于编号最大的亮的那个灯,你想让它灭掉,只有两个方法。

一个是按掉它的开关,另一个是按掉比它更大的开关。

但是因为这已经是亮的里编号最大的了,那么如果你按一个编号更大的开关,那么亮的灯泡里编号上界就更大了。

这样的话迟早会涨到n左右,然后这时候我们只能关闭它自己。。。然后直到恢复初始状态。

所以你当然会直接按掉它自己。

这之后编号最大的亮灯编号变小了,继续同理解决问题即可。

这样我们就拿到了这个部分分。

但是直到这里,和我们的dp还是没有什么关系。

但是我们可以发现一些性质:

任意一个开关,都不能被其它的开关集合等价代替。

这样的话,给定我们一个初始状态,我们能像那个部分分一样求出它需要的开关集合。

这样的话,我们就可以断言,那些开关需要你动,那些开关你不能动。

而它是随机操作的,那么如果动了那些你不能动的开关。。。那么你还得再动一次让它回复原状

这就是异或操作,具有“操作偶数次等于没操作”和“交换操作顺序结果不变”的性质。

到了这里,我们开始构造dp数组的含义。

我们发现,现在开关到底是什么已经不重要了,开关只有两种:你需要动的,你不能动的

那么其实你只需要知道你还需要动几个开关就可以了

设$dp[i]$表示还有i个开关需要操作,想按对一个开关期望需要多少次操作。考虑转移:

你有$\frac{i}{n}$的概率按对,那么就是$\frac{i}{n}$

你有$\frac{n-i}{n}$的概率按错,这时候需要按的变成了$i+1$个,

于是先按$1$下到$i+1$步,再回来是$dp[i+1]$,而且你还要再按掉一个,是$dp[i]$。

于是$dp[i]=\frac{i}{n} + \frac{n-i}{n} \times (dp[i+1]+dp[i]+1)$

把$dp[i]$合并同类项,再化一下系数,得到$dp[i]=1+\frac{n-i}{i}\times (dp[i+1]+1)$

那么答案就是先把原有的cnt个按成k个,再把k个用最优决策判掉。

$ans=k+\sum\limits_{i=k+1}^{cnt} dp[i]$

当然如果cnt<=k的话答案就是cnt啊。

最后按照题意乘上$n!$即可。

 #include<cstdio>
#define mod 100003
#define int long long
int dp[mod],st[mod],cnt,n,k,ans;
int qp(int b,int t,int a=){for(;t;t>>=,b=b*b%mod)if(t&)a=a*b%mod;return a;}
main(){
scanf("%lld%lld",&n,&k);
for(int i=;i<=n;++i)scanf("%lld",&st[i]);
for(int i=n;i;--i)if(st[i]){
cnt++;
for(int j=;j*j<=i;++j)if(i%j==){
st[j]^=;if(j*j!=i)st[i/j]^=;
}
}
if(cnt<=k){
for(int i=n;i;--i)cnt=cnt*i%mod;
printf("%lld\n",cnt);
return ;
}
dp[n]=;
for(int i=n-;i;--i)dp[i]=((n-i)*qp(i,mod-)%mod*(dp[i+]+)+)%mod;
for(int i=k+;i<=cnt;++i)ans=(ans+dp[i])%mod;ans+=k;
for(int i=n;i;--i)ans=ans*i%mod;
printf("%lld\n",ans);
}

好题,思路很不错。

其实这么顺下来貌似不是很难,但是为什么想不出来呢?

我和正解思路之间的距离。。。

还需要多练啊。

分手是祝愿:dp的更多相关文章

  1. bzoj 4872: [Shoi2017]分手是祝愿 [期望DP]

    4872: [Shoi2017]分手是祝愿 题意:n个灯开关游戏,按i后i的约数都改变状态.随机选择一个灯,如果当前最优策略\(\le k\)直接用最优策略.问期望步数\(\cdot n! \mod ...

  2. [BZOJ4872][六省联考2017]分手是祝愿(期望DP)

    4872: [Shoi2017]分手是祝愿 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 516  Solved: 342[Submit][Statu ...

  3. 【BZOJ4872】[Shoi2017]分手是祝愿 数学+期望DP

    [BZOJ4872][Shoi2017]分手是祝愿 Description Zeit und Raum trennen dich und mich. 时空将你我分开.B 君在玩一个游戏,这个游戏由 n ...

  4. BZOJ 4872 luogu P3750 [六省联考2017]分手是祝愿

    4872: [Shoi2017]分手是祝愿 Time Limit: 20 Sec  Memory Limit: 512 MB[Submit][Status][Discuss] Description ...

  5. 【BZOJ4872】分手是祝愿

    分手是祝愿 [题目大意] 有n 个灯,每个灯有两个状态亮和灭,我们用 1 来表示这个灯是亮的,用 0 表示这个灯是灭的,操作第 i 个开关时,所有编号为 i 的约数(包括 1 和 i)的灯的状态都会被 ...

  6. 【BZOJ4872】分手是祝愿(动态规划,数学期望)

    [BZOJ4872]分手是祝愿(动态规划,数学期望) 题面 BZOJ 题解 对于一个状态,如何求解当前的最短步数? 从大到小枚举,每次把最大的没有关掉的灯关掉 暴力枚举因数关就好 假设我们知道了当前至 ...

  7. BZOJ_4872_[Shoi2017]分手是祝愿_概率与期望

    BZOJ_4872_[Shoi2017]分手是祝愿_概率与期望 Description Zeit und Raum trennen dich und mich. 时空将你我分开.B 君在玩一个游戏,这 ...

  8. bzoj千题计划266:bzoj4872: [六省联考2017]分手是祝愿

    http://www.lydsy.com/JudgeOnline/problem.php?id=4872 一种最优解是 从大到小灯有亮的就灭掉 最优解是唯一的,且关灯的顺序没有影响 最优解 对每个开关 ...

  9. 2017 [六省联考] T5 分手是祝愿

    4872: [Shoi2017]分手是祝愿 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 458  Solved: 299[Submit][Statu ...

  10. SHOI2017 分手是祝愿

    分手是祝愿 有

随机推荐

  1. scalikejdbc 学习笔记(3)

    重用connection: package com.citi.scalikejdbc import scalikejdbc._ import scalikejdbc.config._ object C ...

  2. centos7 scrapy安装

    1.anaconda3安装 wget https://repo.anaconda.com/archive/Anaconda3-2019.03-Linux-x86_64.sh 安装报错,可能是源的问题 ...

  3. 通过搭建MySQL掌握k8s(Kubernetes)重要概念(上):网络与持久卷

    上一篇"通过实例快速掌握k8s(Kubernetes)核心概念"讲解了k8s的核心概念,有了核心概念整个骨架就完整了,应付无状态程序已经够了,但还不够丰满.应用程序分成两种,无状态 ...

  4. 卷积神经网络CNN识别MNIST数据集

    这次我们将建立一个卷积神经网络,它可以把MNIST手写字符的识别准确率提升到99%,读者可能需要一些卷积神经网络的基础知识才能更好的理解本节的内容. 程序的开头是导入TensorFlow: impor ...

  5. Jquery的load加载本地文件出现跨域错误的解决方案

    如果用原生的AJAX是加载本地文件就不会出现错误.当然,这个jquery的load放在服务器上通过http加载还是支持的.也有例外比如在firefox和ie浏览器使用$.ajax加载本地html或tx ...

  6. Java课程作业--参数求和

    一.设计思想: 这个程序是利用了参数进行输入,达到一次可以输入多个值的问题,同时输入数的个数没有限制(参数大于0个,如果为0个,应该输出提示请输入参数).本程序共分为步:1.利用参数行进行输入要加的数 ...

  7. 洛谷NOIp热身赛 T2123 数列游戏

    题目背景 此题为改编题,特别鸣谢倪星宇同学. 有一次,HKE和LJC在玩一个游戏. 题目描述 游戏的规则是这样的:LJC在纸上写下两个长度均为N的数列A和B,两个数列一一对应.HKE每次可以找两个相邻 ...

  8. Python历史+优缺点+应用领域+网站职位简介

    一.Python的历史 1. 1989年圣诞节:Guido von Rossum开始写Python语言的编译器.2. 1991年2月:第一个Python编译器(同时也是解释器)诞生,它是用C语言实现的 ...

  9. Redis实现分布式文件夹锁

    缘起 最近做一个项目,类似某度云盘,另外附加定制功能,本人负责云盘相关功能实现,这个项目跟云盘不同的是,以项目为分配权限的单位,同一个项目及子目录所有有权限的用户可以同时操作所有文件,这样就很容易出现 ...

  10. Java反序列化漏洞总结

    本文首发自https://www.secpulse.com/archives/95012.html,转载请注明出处. 前言 什么是序列化和反序列化 Java 提供了一种对象序列化的机制,该机制中,一个 ...