首页 > 其他分享 >NOIP模拟A2

NOIP模拟A2

时间:2023-06-12 21:47:17浏览次数:40  
标签:frac NOIP int sqrt times A2 模拟 物品 dp

好像是去年 8 月 1 日的模拟赛,主题采自南昌起义。

背景


A. 南

一道可爱的期望 DP。

一般来说,期望 DP 都是逆推,从最终状态往前推,这题也不例外。

这道题难度主要在于,第 \(k\) 次购买的价格为 \(k\),即价格与购买次数有关。

那我们就不能直接进行转移了,而是需要根据期望次数进行转移。

所以我们定义 \(f[i]\) 为已经获得 \(i\) 种武器,想要获得 \(n\) 种武器的期望次数。

初始状态 \(f[n] = 0\),即已经获得 \(n\) 种武器后想要取完 \(n\) 种武器的期望次数为 \(0\)。

\(f[i]\) 的转移还是很容易能想到的,分两种情况处理。

  1. 买到了已经有的类型,得到 \(f[i] = f[i] + 1\),已经获得的武器种类数保持不变,仍然为 \(i\)。
  2. 买到之前没有的类型,得到 \(f[i] = f[i+1]+1\),拥有的武器种类数增加了 \(1\)。
    于是我们得到式子:

\[f[i] = \frac{i}{n} \times (f[i] + 1) + \frac{n-i}{n}\times (f[i + 1]+1) \]

这个式子可以化简

\[f[i] = f[i + 1] + \frac{n}{n-i} \]

定义 \(g[i]\) 为已经获得 \(i\) 种武器,想要获得 \(n\) 种武器的期望钱数。

同理,初始状态为 \(g[i] = 0\),仍然分取到已经有的和取到没有的两种情况处理。

\[g[i] = \frac{i}{n}\times(g[i] + f[i] + 1) + \frac{n-i}{n}\times(g[i + 1]+f[i+1]+1) \]

每次加的钱数都是在上一次的基础上加了 \(1\),无论是买到已获得的还是未获得的。

这个式子仍然可以化简:

\[g[i] = \frac{i}{n-i}\times f[i] + g[i + 1]+f[i + 1]+\frac{n}{n-i} \]

Code:

for(int i = n - 1;i >= 0; i--)
		f[i] = f[i + 1] + (double)n / (double)(n - i);
	for(int i = n - 1;i >= 0; i--)
		g[i] = (double)i / (double)(n - i) * f[i] + g[i + 1] + f[i + 1] + (double)n / (double)(n - i);

B. 昌

要求根结点的最大值。

我们先假设根结点的最大值大于等于 \(x\),那么对于 \(\text{min}\) 操作来说,儿子的权值必须都大于等于 \(x\);对于 \(\text{max}\) 操作来说,儿子的权值至少要有一个大于等于 \(x\)。

依次类推,我们就可以找到这棵树有多少叶子结点的权值需要大于等于 \(x\),设这个值为 \(cnt\),那么 \(x\) 的最大值就是 \(k - cnt + 1\),\(k\) 为叶子个数。

所以我们可以求出来 \(cnt\),用它来求 \(x\)。

设 \(f[u]\) 为以 \(u\) 为根的子树内,至少有 \(f[u]\) 个叶子结点需要大于某个值。

对于叶子结点,有 \(f[u] = 1\)。

对于 \(\text{max}\) 操作:\(f[u] = \text{min}_{v \in son[u]}f[v]\)
对于 \(\text{min}\) 操作:\(f[u] = \Sigma_{v \in son[u]} f[v]\)

(对应的就是最开始那几句)

最终答案为 \(k - f[1] + 1\)。

Code:

void dfs(int x) {
	if(e[x].empty()) {
		dp[x] = 1;
		return;
	}
	
	if(a[x] == 1) {
		dp[x] = INT_MAX >> 1;
		for(int i : e[x]) {
			dfs(i);
			dp[x] = min(dp[x],dp[i]); 
		}
	} else {
		dp[x] = 0; 
		for(int i : e[x]) {
			dfs(i);
			dp[x] += dp[i]; 
		}
	}
}

C. 起

不想写了,挂个官方题解

D. 义

好像是根号分治。

一个没听说过的东西,考后查了查,是一种思想,将要处理的整体分为前 \(\sqrt{n}\) 和剩余部分分别处理。

在这道题里十分的明显。

对于前 \(\sqrt{n}\) 种物品,每一种物品都有取完的可能。

但对于 \(\sqrt{n} + 1\) 到 \(n\) 种物品,如果把物品取完,就会超过背包容量,所以物品都取不完,相当于物品数量是无穷的。

所以我们可以分开进行 DP。

对于前 \(\sqrt{n}\) 种物品,定义 \(f[i][j]\) 为取完第 \(i\) 种物品,背包容量已经用 \(j\)。

\[f[i][j] = f[i-1][j] + f[i][j-i]-f[i-1][j-i \times (i +1)] \]

假设有一条线段,表示我们背包的容量。

\(f[i-1][j]\) 表示不拿 \(i\) 物品,\(f[i][j-i]\) 表示再拿一个 \(i\) 物品,要减去多拿的方案数。


对于 \(f[i][j]\),是由 \(f[i][j - i]\) 转移而来的,\(f[i][j - i]\) 是由 \(f[i][j - 2i]\) 转移而来,但显然,不能拿 \(i(i+1)\) 个或以上,所以需要减去这部分。

再考虑剩下的部分,定义 \(g[i][j]\) 表示拿了 \(i\) 件 \(\sqrt{n} + 1\) 到 \(n\) 的物品,使用背包容量为 \(j\),有

\[g[i][j + i] = g[i][j+i]+g[i][j] \]

表示每个物品都增加 \(1\) 的容量,变成下一种物品,就是不拿第 \(\sqrt{n} + 1\) 种物品

\[g[i][j + \sqrt{n} +1] = g[i][j + \sqrt{n} +1] + g[i][j] \]

表示拿一个第 \(\sqrt{n} +1\) 种物品。

最后把两个数组的方案数相乘相加。

Code:

    m = sqrt(n);
    f[0][0] = f[1][0] = 1;

    int k = 0;

    for (int i = 1; i <= m; i++) {
        k ^= 1;
        for (int j = 1; j <= n; j++) {
            f[k][j] = f[k ^ 1][j];

            if (j >= i)
                f[k][j] = (f[k][j] + f[k][j - i]) % MOD;

            if (j >= i * (i + 1))
                f[k][j] = (f[k][j] - f[k ^ 1][j - i * (i + 1)] + MOD) % MOD;
        }
    }

    g[0][0] = 1;
    for (int i = 0; i <= m; i++) 
        for (int j = 0; j <= n; j++) {
            if (j + i <= n && i)
                g[i][j + i] = (g[i][j + i] + g[i][j]) % MOD;

            if (j + m + 1 <= n)
                g[i + 1][j + m + 1] = (g[i + 1][j + m + 1] + g[i][j]) % MOD;
        }

    g[1][0] = 1;

    for (int i = 0; i <= n; i++)
        for (int j = 1; j <= m; j++)
            ans = (ans + 1ll * f[k][i] * g[j][n - i] % MOD) % MOD;

标签:frac,NOIP,int,sqrt,times,A2,模拟,物品,dp
From: https://www.cnblogs.com/baijian0212/p/17476168.html

相关文章

  • 尚医通-day06【医院模拟系统接口详细步骤】(内附源码)
    第01章-医院系统1、业务功能描述资料:资料>医院模拟系统>尚医通API接口文档.docx1.1、平台方参考《尚医通API接口文档.docx》进行业务接口的开发,接收医院方的接口调用,将医院信息、科室信息、排班信息等数据存入MongoDB。1.2、医院方每个医院有自己的业务平台,需参考《尚医通AP......
  • 洛谷 P6821 [PA2012]Tanie linie
    洛谷传送门考虑恰好选\(k\)个子段怎么做。设恰好选\(i\)个子段的和最大值为\(h_k\)。可以得到\(h_{i+1}-h_i\leh_i-h_{i-1}\),因为\(h_i\toh_{i+1}\)的过程就是多选一个子段,贡献肯定不如上一次选即\(h_{i-1}\toh_i\)大。如果它不成立,那我们可以交换......
  • 数据结构模拟器地址
    数据结构在线模拟器 Github网址:https://github.com/IACJ/react-datastructer在线网址:https://iacj.github.io/react-datastructer/#/  这个在线的模拟器包含“栈”、“队列”、“堆”、“BST”等数据结构,每个数据结构以图像的方式展示在我们面前,同时又有各自的帮助文......
  • python 模拟form表单流式上传文件
    如果机器上有PycURL,那么可以使用PycURL来上传文件。不过,由于PycURL需要用到curl,在Windows下安装可能会有点麻烦,除PycURL外,也有一些其它实现POST文件上传的方式,比如这儿的2楼有人贴出了一个将文件进行编码之后再POST的方法,另外还有MultipartPostHandler、urllib2_......
  • STL之Stack与queue的模拟实现与duque的底层结构(3千字长文详解)
    STL之Stack与queue的模拟实现与duque的底层结构设计模式的概念设计模式像是古代的兵法,是以前的人总结出来的一些在特定的情况下,某种特定的好用的方法总结STL中迭代器也是一种设计模式——==迭代器模式==STL中stack和queue的实现就是使用了一种设计模式——==适配器模式!==适......
  • STL之优先级队列(堆)的模拟实现与仿函数(8千字长文详解!)
    STL之优先级队列(堆)的模拟实现与仿函数优先级队列的概念优先队列是一种==容器适配器==,根据严格的弱排序标准,==它的第一个元素总是它所包含的元素中最大的==。本质就是一个堆!此上下文类似于堆,在堆中可以随时插入元素,并且只能检索最大堆元素(优先队列中位于顶部的元素)。......
  • 模拟终端学习
    xtermxterm,一个模拟出来的终端,解决的是真实机器的输入和输出模拟问题。xterm本质上是应用程序,是个软件,它不同于硬件的输入-键盘、输出-显示器。他是怎么做到模拟的?这个问题到底难在哪?可以通过一个具体的case来体会。假设有一个进程A,作为进程B,进程B怎么向进程A的标准输入一串字......
  • 2023冲刺国赛模拟 15.1
    T1计数首先考虑计数有标号可重叠的方案数,容易发现此时\(x,y\)两维独立,因此考虑其中\(1\)维,设\(f_{i,j}\)表示此时考虑到第\(i\)对左右边界\((x_{i,1},x_{i,2})\),离散化后的\(x\)坐标形成了\(j\)个点时的方案数,容易发现此时数轴上存在\(j\)个点,以及\(j+1\)个空......
  • 3、修改avd模拟器的默认路径
     1、由于avd的默认路径在c盘,如图所示的位置 2、现在将位置进行更改,先在D盘创建文件夹,再将c盘文件夹的内容移动过去  3、配置环境变量 4、修改配置文件  ......
  • 算法刷题记录:P1328 [NOIP2014 提高组] 生活大爆炸版石头剪刀布
    题目链接https://www.luogu.com.cn/problem/P1328题目分析是一道和环有关的问题,直接模拟即可AC代码//Problem:P1328[NOIP2014提高组]生活大爆炸版石头剪刀布//Contest:Luogu//URL:https://www.luogu.com.cn/problem/P1328//MemoryLimit:125MB//TimeLimit......