首页 > 其他分享 >多校A层冲刺NOIP2024模拟赛03 -- T4 量子隧穿问题

多校A层冲刺NOIP2024模拟赛03 -- T4 量子隧穿问题

时间:2024-10-07 20:02:12浏览次数:7  
标签:03 概率 -- T4 int clear 隧穿 钦定

多校A层冲刺NOIP2024模拟赛03 -- T4 量子隧穿问题

$$HZOI$$

感觉是这两天最有意义的题吧。

\(n\) 句话题意

我是巴甫洛夫的狗,我又重生了,重生在薛定谔的家里。

薛定谔是抖S,于是给我铃声。我开始狂跑不止。

为什么没流口水没删除我

给定 \(n\) 个点,对于 \(i\) 存在一条外向连的单向边。对于每个点,存在三种状态,有人无人不确定。

将 \(i\) 从小到大遍历,对于第 \(i\) 个点若存在人,且下一个点无人,则这人将沿边跑到下一个点,否则不动。

对于不确定的点,可能是有人也可能是没人,问有多少种在遍历完最后一个盒子有人的情况。 \(n \le 5000\) (其实 \(1e6\) 大差不差也能过)

题解

这个题就是纯唐。首先我们发现捏,这个东西显然是一个内向基环树。

然后我们不考虑基环树,就考虑普通树,普通树怎么做?

我们发现如果是概率的话,每个点的概率显然就是 \(0\)(无人),\(1\)(有人),\(\frac{1}{2}\)(不确定)。

好像这个可以搞诶……

那么对于一次转移,即从 \(i\) 到其父亲节点,若以 \(k_1\) 表示 \(i\) 点概率, \(k_2\) 表示 \(fa_i\) 的概率。(转移前)

则转移后新概率:

\[\begin{aligned} k_1' &= k_1 \times k_2 \\ k_2' &= (1 - k_2) \times k_1 + k_2 \end{aligned}\]

感觉还是挺显然的……

那只用从小往大依次枚举就好了呀,做完了。

好的,现在来看正解。

那有些长得帅的小伙伴就会问了,这和树有啥区别吗?难道把边重新跑一遍有啥区别吗?

诶,现在有这么一个环:

1 -> 2
 \  / (2 -> 3 , 3 -> 1)
   3

如果 \(1 , 2 , 3\) 全是 \(?\) , 那么对于 \(2\) 来说 \(2\) 是 \(0\) ,\(1\) 号有可能 \(1/0\) , \(3\) 同理,对于处理 \(1 \to 3\),时,可能钦定 \(1\) 号为 \(1\),然而 \(3\) 号可能是由 \(1\) 号为 \(0\) 转移来的。因此有错误。

那有些长得帅的小伙伴们又会说了,不是那咋做?

我们发现错误的原因是由于第一个点重复了,那我们钦定第一个值是啥,那不就不会重复了吗!

只要我们钦定这个环里第一次处理的边的值并确定之,最后乘上其为被钦定的值的概率,加起来,乘总数,就得到答案了。时间复杂度 \(\mathcal{O(n)}\)

完结撒花!!!

Code

CODE
#include <bits/stdc++.h>
typedef long long ll ; 
using namespace std ; 
const int N = 5010 ; 
const int mod = 1e9 + 7 ; 

int T , n ; 
char s[N] ; int b[N] ; 

struct Node {
	int father[N] ; ll Probabit[N] ; 

	inline void clear(int n) {
		for (int i = 1 ; i <= n ; ++ i) father[i] = i ; 
		for (int i = 1 ; i <= n ; ++ i) {
			if (s[i] == '.') Probabit[i] = 0 ; 
			else if (s[i] == 'C') Probabit[i] = 1 ; 
			else Probabit[i] = (mod + 1) / 2 ; 
		}
	}

	int Find_Father(int x) {
		if (x == father[x]) return x ; 
		return father[x] = Find_Father(father[x]) ; 
	}
	bool Combine(int x , int y) {
		return Find_Father(x) == Find_Father(y) ; 
	}
	bool Merge(int x , int y) {
		x = Find_Father(x) , y = Find_Father(y) ; 
		if (x == y) return true ; 
		return father[y] = x , false ; 
	}
} ; 

struct Probability {
	ll Probabit[N] ; 
	
	inline void clear(int n) {
		for (int i = 1 ; i <= n ; ++ i) {
			if (s[i] == '.') Probabit[i] = 0 ; 
			else if (s[i] == 'C') Probabit[i] = 1 ; 
			else Probabit[i] = (mod + 1) / 2 ; 
		}
	}

	void Build_Bridge(int x , int y) {
		ll fir = Probabit[x] , sec = Probabit[y] ; 
		Probabit[y] = ((1 - sec + mod) * fir + sec) % mod ; 
		Probabit[x] = (fir * sec) % mod ; 
	}

	ll Ask() {
		ll ans = 0 ; 

		for (int i = 1 ; i <= n ; ++ i) {
			if (s[i] == '?') ans = (ans * 2ll) % mod ; 
		}

		return (ans * Probabit[n]) % mod ; 
	}

	Probability operator = (Probability b) {
		for (int i = 1 ; i <= n ; ++ i) {Probabit[i] = b.Probabit[i] ; }
		return b ; 
	}
} ; 

Node alpha , beta ; Probability theta , delta ; 

signed main() {
	freopen("experiment.in" , "r" , stdin) ; 
	freopen("experiment.out" , "w" , stdout) ; 
	ios::sync_with_stdio(0) , cin.tie(0) , cout.tie(0) ; 
	cin >> T ; 

	while (T --) {
		cin >> n >> s + 1 ; 
		for (int i = 1 ; i <= n ; ++ i) cin >> b[i] ; 

		alpha.clear(n) , beta.clear(n) ; int xrlong = 0 ; 

		for (int i = 1 ; i <= n ; ++ i) alpha.Merge(i , b[i]) ; 
		for (int i = n ; i >= 1 ; -- i) {
			if (alpha.Combine(i , n) && beta.Merge(i , b[i])) {
				xrlong = i ; 
			}
		}

		theta.clear(n) ; 

		if (!xrlong) {			
			for (int i = 1 ; i <= n ; ++ i) {
				theta.Build_Bridge(i , b[i]) ; 
			}

			cout << theta.Ask() << '\n' ; 
			continue ; 
		} else {
			ll ans = 0 ; 
			char s1 = s[xrlong] , s2 = s[b[xrlong]] ; ll p1 , p2 ; 

			for (int i = 1 ; i < xrlong ; ++ i) theta.Build_Bridge(i , b[i]) ; 
			p1 = theta.Probabit[xrlong] , p2 = theta.Probabit[b[xrlong]] ; 
			for (int x = 0 ; x <= 1 ; ++ x) {
				for (int y = 0 ; y <= 1 ; ++ y) {
					ll now = 1 ; 
					delta = theta ; delta.Probabit[xrlong] = x ; 
					delta.Probabit[b[xrlong]] = y ; 
					now = ((x == 0 ? 1 + mod - p1 : p1) * (y == 0 ? 1 + mod - p2 : p2)) % mod ; 

					for (int i = xrlong ; i <= n ; ++ i) {
						delta.Build_Bridge(i , b[i]) ; 
					}

					now = (now * delta.Probabit[n]) % mod ; (ans += now) %= mod ; 
				}
			}

			for (int i = 1 ; i <= n ; ++ i) 
				if (s[i] == '?') ans = (ans * 2) % mod ; 
			cout << ans << '\n' ; 
		}
	}
}

标签:03,概率,--,T4,int,clear,隧穿,钦定
From: https://www.cnblogs.com/hangry/p/18450532

相关文章

  • 鲁的女孩 题解
    题意给两个数列,对它进行排列,使得对应两数的和的最大值最小。题解贪心,先将\(a\)、\(b\)排个序(先不考虑时间)。将\(a_1\)与\(a_n\)匹配。\(a_2\)与\(a_{n-1}\)匹配。……取最大值即可。考虑到\(n\le10^5\),不可以暴力枚举。但是\(a,b\le100\),可以开一个桶,......
  • P1443
    又忘发博客了啊啊啊啊啊啊啊马的遍历竟然现在才写……模板bfs。#include<bits/stdc++.h>usingnamespacestd;queue<int>_x,_y;intma[405][405],dx,dy;intqx[8]={1,1,2,2,-1,-1,-2,-2};intqy[8]={-2,2,-1,1,2,-2,1,-1};intmain(){ intn,m,x,y; cin>>n>>m>>......
  • 题解 QOJ1869【Power Station of Art】/ SS241006B【结论题】
    题解QOJ1869【PowerStationofArt】/SS241006B【结论题】PetrozavodskSummer2021.Day6.XJTUContest,GPofXJTUXXIIOpenCupnamedafterE.V.Pankratiev,GrandPrixofXi'an题目描述给出一个无向图,每个点有点权\(a\)和颜色\(c\),其中颜色只会有红蓝两种。......
  • CF131C题解
    传送门:https://codeforces.com/problemset/problem/134/C关注到题目的两个限制:1.一个人只能与另外同一人交换一张卡牌。2.一个人只能交换自己原来颜色的卡牌。对于2条限制条件,显然有贪心思路:尽量让更多的人手持原有的卡牌。对于当前待交换的卡牌,一种构造思路,我们每次贪心选取......
  • 『模拟赛』多校A层冲刺NOIP2024模拟赛03
    Rank炸了,触底反弹A.五彩斑斓(colorful)签,又没签上。考虑如何一步步优化暴力。最暴力的思想\(\mathcal{O(n^4)}\)枚举每个矩形,判断四个顶点颜色。稍微优化些,两次\(\mathcal{O(n^2)}\)跑出对于行/列每个点下一个与之颜色相同的坐标,利用容斥全部减去不合法的方案数,然后再枚......
  • Vue3 hooks----实现组合式API
    hooks实现将一个功能的所有数据、方法、生命周期函数放到一块去使用。我们在src底下定义个Hooks文件夹,将我们要进行模块化的功能设置为use功能名。例如:我要将点我加一这个功能进行hooks,则使用useSum.ts这个文件定义功能逻辑。在这个ts里面需要export default 函数这种写法,......
  • 伊吹萃香 题解
    题意(很复杂,真的不想概括,以下是原题面)在幻想乡,伊吹萃香是能够控制物体密度的鬼王。因为能够控制密度,所以萃香能够制造白洞和黑洞,并可以随时改变它们。某一天萃香闲着无聊,在妖怪之山上设置了一些白洞或黑洞,由于引力的影响,给妖怪们带来了很大的麻烦。于是他们决定找出一条消耗体力......
  • 线程池
    线程池是一种用于管理和复用线程的技术,主要目的是提高系统性能和资源利用率。它通过预先创建一定数量的线程,并将它们保存在线程池中,当需要执行任务时,从线程池中获取一个空闲的线程来执行任务,而不是每次都创建新的线程¹²。线程池的工作原理线程池初始化:在应用程序启动时,线......
  • ME 588, Dynamics and Vibration
    ME588,DynamicsandVibrationHomework1Distributed:9/25/2024,Due:10/11/20241.Consideraspring-masssystemmountedonaspinningdiskasshowninFig.1.Thediskspinsatconstantangularvelocityω.Moreover,thediskhasadiametricalslot,alo......
  • 【Python数据采集】国家自然科学基金大数据知识管理服务门户数据采集
    【Python数据采集】国家自然科学基金大数据知识管理服务门户数据采集具体需求:从https://kd.nsfc.cn/网站中根据关键词搜索项目信息,收集列表中展示的信息以及详情页面中的参与人员信息等。在开始干活之前,我们首先要做的是弄清楚需求,然后分析目标网址,确定目标数据所在接口及请求参......