2021牛客多校6 - Gambling Monster(分治FWT优化期望dp)

Posted Frozen_Guardian

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2021牛客多校6 - Gambling Monster(分治FWT优化期望dp)相关的知识,希望对你有一定的参考价值。

题目链接:点击查看

题目大意:有一个转盘,每次转动得到 0 ∼ n − 1 0\\sim n−1 0n1 n n n 是 2 的幂)的概率分别给出。最开始你有一个数 x = 0 x=0 x=0,每次转动转盘得到一个数 y y y,如果 x ⊕ y > x x\\oplus y>x xy>x,就令 x = x ⊕ y x=x\\oplus y x=xy,否则 x x x 不变。求使 x = n − 1 x=n-1 x=n1,期望转动转盘的次数。

题目分析:

求期望,考虑倒着的概率 d p dp dp

P [ i ] P[i] P[i] 为转到 i i i 的概率,设 E [ i ] E[i] E[i] 代表当前数字为 i i i,到达 n − 1 n-1 n1 的期望步数,显然 E [ n − 1 ] = 0 E[n-1]=0 E[n1]=0,答案是 E [ 0 ] E[0] E[0]

S [ x ] S[x] S[x] 代表转动一次转盘后 x x x 发生变化的概率(即变大)的概率,不难得到 S [ x ] = ∑ x ⊕ y > x P [ y ] S[x]=\\sum\\limits_{x\\oplus y>x}P[y] S[x]=xy>xP[y]

那么 E E E 的方程分成两个部分也不难写出: E [ x ] = ( E [ x ] + 1 ) ∗ ( 1 − S [ x ] ) + ∑ x ⊕ y = z x < z ( E [ z ] + 1 ) ∗ P [ y ] E[x]=(E[x]+1)*(1-S[x])+\\sum\\limits_{\\overset{x<z}{x\\oplus y=z}}(E[z]+1)*P[y] E[x]=(E[x]+1)(1S[x])+xy=zx<z(E[z]+1)P[y]

发现左右两侧都有 E [ x ] E[x] E[x],所以移一下项得到:
E [ x ] = ( 1 − S [ x ] ) + ∑ x ⊕ y = z x < z ( E [ z ] + 1 ) ∗ P [ y ] S [ x ] E[x]=\\frac{(1-S[x])+\\sum\\limits_{\\overset{x<z}{x\\oplus y=z}}(E[z]+1)*P[y]}{S[x]} E[x]=S[x](1S[x])+xy=zx<z(E[z]+1)P[y]

对于 S [ x ] S[x] S[x],我们发现只需要找到 y y y 在二进制下最高位的 1 1 1,判断一下在 x x x 在二进制下是否为 0 0 0 就可以确定是否存在贡献,这个可以 O ( n l o g n ) O(nlogn) O(nlogn) 预处理出来

对于 ∑ x ⊕ y = z x < z ( E [ z ] + 1 ) ∗ P [ y ] \\sum\\limits_{\\overset{x<z}{x\\oplus y=z}}(E[z]+1)*P[y] xy=zx<z(E[z]+1)P[y],不难发现是异或卷积的形式,又因为期望 d p dp dp 是倒着推的,所以后面的答案会对前面的答案具有贡献,这个可以用 c d q cdq cdq 分治套 F W T FWT FWT 来解决

需要注意的是,在分治的过程中后面的答案会影响前面的答案,所以我们需要先递归右子区间,然后再递归左子区间

最后就是如何确定公式中 y y y 的取值范围呢,如果每次都是取 0 ∼ n − 1 0\\sim n-1 0n1 的话肯定不行,通过分析不难发现,每次拆出来的左右区间形如:
[ x x x 0000 ] ∼ [ x x x 0111 ] + [ x x x 1000 ] ∼ [ x x x 1111 ] [xxx0000]\\sim[xxx0111]+[xxx1000]\\sim[xxx1111] [xxx0000][xxx0111]+[xxx1000][xxx1111]

我们上述式子中的 x x x 需要在左区间中取, z z z 需要在右区间中取,而 y y y 只需要满足 y = x ⊕ z y=x\\oplus z y=xz 即可,将上面的两段区间进行异或可以得到 y ∈ [ 1000 , 1111 ] y\\in[1000,1111] y[1000,1111],这个每次通过位运算求解即可,不难发现 y y y z z z 的区间刚好是等阶的

代码:

// Problem: Gambling Monster
// Contest: NowCoder
// URL: https://ac.nowcoder.com/acm/contest/11257/D
// Memory Limit: 524288 MB
// Time Limit: 2000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

// #pragma GCC optimize(2)
// #pragma GCC optimize("Ofast","inline","-ffast-math")
// #pragma GCC target("avx,sse2,sse3,sse4,mmx")
#include<iostream>
#include<cstdio>
#include<string>
#include<ctime>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<stack>
#include<climits>
#include<queue>
#include<map>
#include<set>
#include<sstream>
#include<cassert>
#include<bitset>
#include<list>
#include<unordered_map>
#define lowbit(x) (x&-x)
using namespace std;
typedef long long LL;
typedef unsigned long long ull;
template<typename T>
inline void read(T &x)
{
	T f=1;x=0;
	char ch=getchar();
	while(0==isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
	while(0!=isdigit(ch)) x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
	x*=f;
}
template<typename T>
inline void write(T x)
{
	if(x<0){x=~(x-1);putchar('-');}
    if(x>9)write(x/10);
    putchar(x%10+'0');
}
const int inf=0x3f3f3f3f;
const int N=1e6+100;
const int mod=1e9+7;
int n;
LL P[N],S[N],invS[N],E[N],tmp[20],a[N],b[N];
LL q_pow(LL a,LL b) {
	LL ans=1;
	while(b) {
		if(b&1) {
			ans=ans*a%mod;
		}
		a=a*a%mod;
		b>>=1;
	}
	return ans;
}
LL inv(int x) {
	return q_pow(x,mod-2);
}
void FWTxor(LL *f,int x,int len)
{
	for(int mid=1;(mid<<1)<=len;mid<<=1)
	{
		int R=mid<<1;
		for(int i=0;i<len;i+=R)
			for(int j=0;j<mid;j++)
			{
				f[i+j]=(f[i+j]+f[i+j+mid])%mod;
				f[i+j+mid]=(f[i+j]-f[i+j+mid]+mod-f[i+j+mid]+mod)%mod;
				f[i+j]=f[i+j]*x%mod;
				f[i以上是关于2021牛客多校6 - Gambling Monster(分治FWT优化期望dp)的主要内容,如果未能解决你的问题,请参考以下文章

2021牛客多校6 - Hopping Rabbit(矩形取模+扫描线)

2021牛客多校6 - Defend Your Country(点双缩点求割点)

2021牛客多校2 - Girlfriend(球体积交)

2021牛客多校8 D.OR(位运算)

2021牛客多校9 E.Eyjafjalla(dfs序+主席树)

2021牛客多校5 B Boxes