省选模拟测试15
期望得分:\(0+40+50=90\)
实际得分:\(0+50+50=100\)
\(T1\) 题面太长最后没时间看这道题了。
\(T2\) 只会打 \(O(n^2)\) 的暴力,正解好像 \(200\) 多行的样子。
\(T3\) 只会写链上和 \(O(n^2)\) 的暴力。
考试的时候打完暴力就一直在想后两道题的正解,但都没想出来。
T1 virus
题目内容
kbs-homo 噬菌体是下北泽生物学家李天梭近期发现并命名的病毒,这种病毒可以在各种极端环境下生存且在常温下极易扩增。
一个质量为 \(x(x>1)\) 的 kbs-homo 噬菌体的扩增过程分为 \(3\) 个阶段如下:
- 如果 \(x\) 为质数,则不分裂且质量变为 \(1\) ,直接结束扩增过程; 否则在区间 \((1,x)\) 中整除 \(x\) 的所有数中等概率选择一个数 \(y\). 病毒分裂成质量为 \(y\) 和质量为 \(\frac{x}{y}\) 的两部分。
- 分裂出的两部分各自复制一份,用来复制的两个母体进行一次扩增。
- 设当前的四个病毒质量为 \(y,\frac{x}{y},a,b\) 其中 \(a,b\) 分别是两个质量为 \(y,\frac{x}{y}\) 的母体扩增之后的质量,四个病毒合并成一个质量为 \(yb+\frac{ax}{y}\) 的病毒。
比如当 \(x=12\) 时,假设第一次扩增随机出 \(y=3\), 此时复制之后为 \(3,4,3,4\) 的四个病毒,质量为 \(3\) 的病毒质量变为 \(1\),质量为 \(4\) 的病毒由于只有一个满足条件的因数 \(2\) ,所以只会扩增出质量为 \(2\times 1+2\times 1=4\) 的病毒。第三阶段时四个病毒质量为 \(3,4,1,4\) , 合并之后质量为 \(3\times4+4\times 1=16\) .
容易证明 kbs-homo 噬菌体的扩增过程一定是有限的。
除了本体扩增以外,在某种环境下,多个噬菌体也会发生融合,融合之后的质量为所有噬菌体的质量乘积。
现在,你作为李天梭教授的助手,你需要帮助他估算一些实验的结果,具体的说,教授收集了 \(n\) 种 kbs-homo 噬菌体, 编号为 \(i\) 的噬菌体质量为 \(a_i\) , 他准备进行 \(Q\) 次实验,第 \(j\) 次实验选取编号在 \(l_j\) 到 \(r_j\) 的噬菌体各一个,将其混合加入金黄色的液体(可能是 Au 和 Cu 合金的熔融物)中在 1145.14 °C的高温下和高压的环境里使它们融合,融合之后用神必手法取出使其扩增一次。由于病毒扩增不稳定,所以教授只对扩增后病毒的期望质量感兴趣,经过评估,教授觉得计算出具体的期望数值对你来说依然十分困难,你只需要帮助教授比较扩增之后的噬菌体期望质量和原质量的大小关系即可,如果期望质量小于原质量输出 \("Smaller"\), 否则输出 \(“Bigger"\) ,(均不含引号)。
由于自然界中出现的 kbs-homo 噬菌体质量都偏向随机 (为了避免精度误差) ,所以教授的实验中不会出现扩增后期望质量和原质量的相对误差小于 \(10^{-6}\) 的情况,即令扩增后期望质量为 \(E\), 原质量为 \(M \frac{|E-M|}{M}\ge 10^{-6}\).
数据范围:\(1\le n\le 30,1\le Q\le 900,1\le l_i\le r_i\le n,2\le a_i\le 100\)
solution
结论题。
设 \(f(x)\) 表示质量为 \(x\) 的噬菌体分裂之后的质量的期望。
不难发现:\(\displaystyle f(x) = {1\over d(x)} \times \sum_{y\mid x} y\times f({x\over y}) + {x\over y}\times f(y), d(x) 表示x的约数个数\) .
通过打表可以发现:\(y\times f({x\over y}) + {x\over y} \times f(y)\) 的值都是相同的。
所以我们的柿子就可以转化为:\(f(x) = y\times f({x\over y}) + {x\over y}\times f(y)\) 。
有一个结论:设 \(\displaystyle x = \prod_{i}^{k} p_i\) 那么 \(f(x) = x\times \sum_{i} {1\over p_i}\) 。
考虑用归纳法证明这个柿子。
首先当 \(x\) 为质数的时候显然符合这个柿子。
当 \(x\) 不为质数的时候,考虑设 \(y\) 的质因子集合 \(S = \{i_1,i_2,i_3....\}\) ,则有:
\(\displaystyle f(x) = (\prod_{i\in S} p_i \prod_{i\notin S}p_i\sum_{i\notin S} {1\over p_i}) + (\prod_{i\notin S} p_i\prod_{i\in S} p_i + \sum_{i\in S}{1\over p_i})\)
合并同类项之后扩发现 \(f(x) = \prod_{i}p_i \times \sum_{i}{1\over p_i}\) 。
然后又因为 \(\prod_{i}p_i = x\) ,所以 \(f(x) = x\times \sum_{i}{1\over p_i}\) 。
由于题目要我们比较的是 \(x\) 和 \(f(x)\) 的大小,所以只需要判断 \(\sum_i{1\over p_i}\) 是否大于 \(1\) 即可。
Code
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
const int N = 1e5+10;
int n,q,l,r;
int num[N],a[N];
double sum[N];
inline int read()
{
int s = 0,w = 1; char ch = getchar();
while(ch < '0' || ch > '9'){if(ch == '-') w = -1; ch = getchar();}
while(ch >= '0' && ch <= '9'){s = s * 10 + ch - '0'; ch = getchar();}
return s * w;
}
int main()
{
n = read(); q = read();
for(int i = 1; i <= n; i++) a[i] = read();
for(int i = 1; i <= n; i++)
{
int x = a[i];
sum[i] = sum[i-1];
for(int j = 2; j <= sqrt(x); j++)
{
while(x % j == 0) sum[i] += 1.0/j, x /= j;
}
if(x > 1) sum[i] += 1.0/x;
}
for(int i = 1; i <= q; i++)
{
l = read(); r = read();
{
if(sum[r]-sum[l-1] >= 1) printf("Bigger\n");
else printf("Smaller\n");
}
}
return 0;
}
T2 streeing
题意描述
给定一棵 \(n\) 个节点的树,树上的每个节点有一个字符 \(c_i\).
初始给出串 \(S\) ,现在有 \(Q\) 次询问 \((x,y)\) ,你需要将 \(x\) 到 \(y\) 路径上的字符拼成一个字符串并回答串 \(S\) 在其中出现了多少次。
数据范围:\(2\le n,Q,|S|\le 10^5\)
solution
树上莫队维护哈希。
这题好像是 [CTSC2010]珠宝商 的弱化版。
直接搬题解吧,口胡起来太麻烦了。
考虑树上莫队,那么我们需要解决的问题就是在某个序列首尾插入字符,删除字符和查询固定串的匹配数量,那么容易发现每一次修改最多只会对匹配数量贡献 , 我们只需要判断一个位置是否有匹配。
使用双端队列维护当前的序列,对字符串哈希,那么我们需要快速查询某两个点对应路径的哈希值,这部分可以预处理所有点到根的哈希值就可以 \(O(1)\) 查询了。
最后时间复杂度 \(O(Q\sqrt{n})\)。
update:这个题拿暴力剪枝就可以艹过去,就nm离谱。
code
//咕咕咕
T3 Tree Querys
题意描述
给定一棵 \(n\) 个节点树,树上的每个节点有一个权值 \(a_i\)。
现在有 \(Q\) 次询问 \((u,d,k)\), 你需要将所有距离点 \(u\) 小于等于 \(d\) 的点的点权排序并输出第 \(k\) 小的点权,如果没有第 \(k\) 小输出 \(-1\).
数据范围:\(0\le a_i\le 10^9,1\le n,Q\le 50000,1\le u_i,v_i,d,k\le n\)
solution
点分树套主席树。
正解没怎么看懂,所以这篇题解被鸽了。