终于下定决心要把整套题做完了。
最早认识这套题不是因为什么板刷,也不是因为什么模拟赛,而是这套题目标题里清一色的"pony",我想这也是为什么我会管这套题叫信仰之题吧(笑)。
不过这套题真的是小马相关的!而且似乎还是中国同志们出的题!有趣!
不过既然主题摆在这里,我也就不管那么多喊一句“云宝黛茜是最棒的小马”吧。(顺便抱走,你们谁也别和我抢!)
废话不多说,从第一题开始走起!
暮暮:马马碰……
Codeforces 454A - Little Pony and Crystal Mine
题面翻译
暮光闪闪有一次从水晶矿里得到了一块水晶。一块大小为$n$($n$是奇数且$n>1$)的水晶看上去是个嵌有一个菱形的$n\times n$矩阵。
现在给你一个奇数$n$。你需要绘制出大小为$n$的水晶的图示。矩阵中的钻石(译者注:或者说水晶,但原文如此)部分用字母"D"表示。其余部分则用字母"*"表示。你可以通过下面的样例来更好地理解你所需绘制的图形。
输入描述
输入仅包含一个整数$n$($3\leq n\leq101$; $n$是奇数)。
输出描述
输出大小为$n$的水晶的图示。
输入样例
样例1
3
样例2
5
样例3
7
输出样例
样例1
*D* DDD *D*
样例2
**D** *DDD* DDDDD *DDD* **D**
样例3
***D*** **DDD** *DDDDD* DDDDDDD *DDDDD* **DDD** ***D***
思路
这个题目就不用说什么思路了吧……完全按照题面模拟输出就可以了,签到题。复杂度$O(n^2)$。
不过……马国的宝石也不值钱,研究那么多做什么。
代码
1 #include <iostream> 2 #include <cstdlib> 3 #include <cstdio> 4 #include <cstring> 5 #include <string> 6 #include <sstream> 7 #include <cctype> 8 #include <cmath> 9 #include <algorithm> 10 #define THE_BEST_PONY "Rainbow Dash" 11 12 using namespace std; 13 14 int n; 15 16 void PrintAns(int x){ 17 for(int i=0;i<(n-x)/2;i++) printf("*"); 18 for(int i=0;i<x;i++) printf("D"); 19 for(int i=0;i<(n-x)/2;i++) printf("*"); 20 printf("\n"); 21 } 22 23 24 int main(){ 25 scanf("%d",&n); 26 for(int i=1;i<=(n-1)/2+1;i++) PrintAns(i*2-1); 27 for(int i=(n-1)/2;i>0;i--) PrintAns(i*2-1); 28 return 0; 29 }
Codeforces 454B - Little Pony and Sort by Shift
题面翻译
有一天,暮光闪闪突然对如何将一个整数序列$a_1, a_2, ...,a_n$排序为一个不下降序列起了兴趣。身为一只年轻独角兽的她,只能进行一种叫做“单元转换”(unit shift)的操作。换句话说,她可以将序列的最后一个元素移动到它的起始位置:
$$a_1, a_2, ...,a_n\rightarrow a_n, a_1, a_2, ...,a_{n-1}$$
请帮助暮光闪闪计算一下:她对这个序列进行排序所需的最小操作次数是多少?
输入描述
第一行一个整数$n (2\leq n\leq10^5)$。
第二行$n$个整数表示$a_1, a_2, ..., a_n (1\leq a_i\leq10^5)$。
输出描述
如果序列无法被排序,输出-1.
否则输出暮光闪闪对它排序所需要的最少操作次数。
输入样例
样例1
2 2 1
样例2
3 1 3 2
样例3
2 1 2
输出样例
样例1
1
样例2
-1
样例3
0
思路
经过仔细观察可以发现,可以通过题中所给的操作进行排序的序列只有两种:
- 序列本身就是不下降的
- 序列可以被从中间分为两个分别不下降的序列,而且序列中的第一个数不小于最后一个数
对于第一种情况答案很明显是0,第二种情况的答案则是后面一段序列的长度。至于其他情况当然是输出-1。
所以说有复杂度为$O(n)$的算法,从头到尾扫一遍即可。
但是……暮暮啊你口算平方根的能力这次又去哪里了?!
代码
1 #include <iostream> 2 #include <cstdlib> 3 #include <cstdio> 4 #include <cstring> 5 #include <string> 6 #include <sstream> 7 #include <cctype> 8 #include <cmath> 9 #include <algorithm> 10 #define THE_BEST_PONY "Rainbow Dash" 11 12 using namespace std; 13 const int maxn=110000; 14 15 int n,pos; 16 int a[maxn]; 17 bool ok=true; 18 19 int main(){ 20 scanf("%d",&n); 21 pos=n; 22 for(int i=0;i<n;i++){ 23 scanf("%d",&a[i]); 24 if(i>0&&a[i]<a[i-1]){ 25 if(pos==n) pos=i; 26 else{ 27 ok=false; 28 break; 29 } 30 } 31 } 32 if(pos!=n&&a[0]<a[n-1]) ok=false; 33 if(!ok) printf("-1"); 34 else printf("%d",n-pos); 35 return 0; 36 }
Codeforces 454C/453A - Little Pony and Expected Maximum
题面翻译
暮光闪闪在和云宝黛茜、苹果杰克和小蝶玩英国十字戏(Ludo,译者注:一种十字戏类游戏,是现代飞行棋的前身)。但是她一直就没赢过。回到城堡后,暮光闪闪对游戏中使用的骰子产生了兴趣。
这个骰子具有$m$面:其中第一面上有一个点,第二面上有两个点,第$m$面上有$m$个点,以此类推。暮光闪闪非常确定当这个骰子被掷出的时候,每一面朝上的概率都是$\frac{1}{m}$。此外她还知道每一次投掷的结果都是独立的。请帮她计算一下,掷这个骰子$n$次得到的最大值的期望是多少。
输入描述
一行两个整数$m$和$n (1\leq m, n\leq10^5)$。
输出描述
输出一个实数,即最大值的期望。当答案的相对或绝对误差没有超过$10^{-4}$时,被视作是正确的。
输入样例
样例1
6 1
样例2
6 3
样例3
2 2
输出样例
样例1
3.500000000000
样例2
4.958333333333
样例3
1.750000000000
样例解释和注释
对于样例3中的情况。如果你掷骰子两次:
- 第一次的值为1,第二次的值为2。最大值为2。
- 第一次的值为1,第二次的值为1。最大值为1。
- 第一次的值为2,第二次的值为1。最大值是2。
- 第一次的值为2,第二次的值为2。最大值是2。
每一种结果的概率都是0.25,因此期望值为:
$$(2+1+2+2)·0.25=\frac{7}{4}$$
你可以在下面的链接中获得更多关于期望的信息:https://zh.wikipedia.org/wiki/期望值
思路
虽然说在现实生活中很显然不存在那样的骰子,但是这很魔法。
题目如果我们可以求出每一个最大值所对应的概率,那么问题就迎刃而解了,令$P_i$是掷$n$次骰子后最大值为$i$的概率,那么答案便是:
$$\sum\limits_{i=1}^{m}P_i\times i$$
那么问题来了——如何才能求出$P_i$呢?
我们令$Q_i$为掷$n$次骰子后最大值不大于$i$的概率,那么很显然$P$和$Q$有如下关系:$P_i=Q_i-Q_{i-1}$.
而$Q_i$是非常容易计算的,只要保证每一次掷骰子的值不大于$i$即可,利用乘法原理可以得到:$Q_i=(\frac{i}{m})^n$.
因此可以推出$P_i$的计算公式:
$$P_i=(\frac{i}{m})^n-(\frac{i-1}{m})^n=\frac{i^n-(i-1)^n}{m^n}$$
进而得到答案的公式:
$$Ans=\sum\limits_{i=1}^{m}i\frac{i^n-(i-1)^n}{m^n}$$
因为直接计算$i^n$会导致溢出,因此需要利用结合律,分别求$(\frac{i}{m})^n$和$(\frac{i-1}{m})^n$来进行避免。
使用快速幂即可,时间复杂度$O(m\log n)$。
代码
1 #include <iostream> 2 #include <cstdlib> 3 #include <cstdio> 4 #include <cstring> 5 #include <string> 6 #include <sstream> 7 #include <cctype> 8 #include <cmath> 9 #include <algorithm> 10 #define THE_BEST_PONY "Rainbow Dash" 11 12 using namespace std; 13 14 int m,n; 15 double ans; 16 17 double qpow(double a,int x){ 18 double re=1; 19 while(x){ 20 if(x&1) re*=a; 21 a*=a; 22 x>>=1; 23 } 24 return re; 25 } 26 27 int main(){ 28 scanf("%d%d",&m,&n); 29 for(int i=1;i<=m;i++) 30 ans+=(qpow(1.0*i/m,n)-qpow(1.0*(i-1)/m,n))*i; 31 printf("%.8lf",ans); 32 return 0; 33 }
Codeforces 454D/453B - Little Pony and Harmony Chest
题面翻译
暮光闪闪公主前往塞拉斯蒂娅和露娜的古堡去研究谐律精华产生的箱子。
一个正整数序列$b_i$被称为谐律数列(译者注:harmony在这里暂且视作谐律之意,若要说成和谐也没什么不妥),当且仅当其中的任意两个元素的最大公约数是1。据一本古书上的记载,箱子的钥匙是一个使下面的式子最小的谐律数列:
$$\sum\limits_{i=1}^{n}|a_i-b_i|$$
现在给你数列$a_i$,请帮助闪闪公主找到钥匙。
输入描述
第一行一个整数$n (1\leq n\leq100)$,为数列$a$和$b$的元素个数。
接下来一行$n$个整数$a_1, a_2, ..., a_n (1\leq a_i\leq30)$。
输出描述
输出钥匙——也就是使上面描述的和最小的合法序列$b_i$。如果有多个序列满足条件,你可以输出其中任意一个。
样例输入
样例1
5 1 1 1 1 1
样例2
5 1 6 4 2 8
样例输出
样例1
1 1 1 1 1
样例2
1 5 3 1 8
思路
首先我们可以发现,如果所有$b_i$的值都是1的话,很显然是一个谐律数列,但是它不一定是最优的。所以我们的问题就变成了如何修改每一个位置上的值,使得它们维持两两互质的同时还能够使得$\sum\limits_{i=1}^{n}|a_i-b_i|$最小。
经过观察我们可以得到一个结论,那就是最终的$b_i$的值是绝对不会超过59的,原因很简单,如果存在$b_i>59$,那么必然有$a_i-1<b_i-a_i$(不要忘了$a_i$最大只有30),那么它必定不是最优的。59之内的素数个数只有17个,那么我们可以想到状压DP,使用整数的二进制位来存储各个质因子的使用情况。
如何判定一个数和当前的质因子使用情况冲突呢?方法很简单,只需要把那个数通过相同的方式进行质因数分解,并用二进制位存储各个质因子的存在情况,那么重复质因子判断就变成了一个简单的与运算。鉴于最终$b_i$的值很小,而且质因数分解的操作会频繁使用,我们需要预处理出所有的分解。
此外再用一个数组记录一下每个状态的决策就行了。
也许代码比上面的话解释得更清楚一点。
(顺便一个剧透:大家辛辛苦苦算出来的$b_i$数列不是箱子的钥匙,不然你要第四季主线干什么?)
代码
1 #include <iostream> 2 #include <cstdlib> 3 #include <cstdio> 4 #include <cstring> 5 #include <string> 6 #include <sstream> 7 #include <cctype> 8 #include <cmath> 9 #include <algorithm> 10 #define THE_BEST_PONY "Rainbow Dash" 11 12 using namespace std; 13 const int maxn=110,maxp=17,maxb=60,INF=~0u>>1; 14 15 int n,pn; 16 int a[maxn],b[maxn][1<<maxp]; 17 int fct[maxn],rd[maxn][1<<maxp]; 18 19 inline int ABS(int x){ 20 return x>0?x:-x; 21 } 22 23 int GetAns(int x,int s){ 24 if(x>n) return 0; 25 if(rd[x][s]!=-1) return rd[x][s]; 26 rd[x][s]=INF; 27 for(int i=1;i<2*a[x];i++){ 28 if(fct[i]&s) continue; 29 if(ABS(a[x]-i)+GetAns(x+1,fct[i]|s)<rd[x][s]){ 30 b[x][s]=i; 31 rd[x][s]=ABS(a[x]-i)+GetAns(x+1,fct[i]|s); 32 } 33 } 34 return rd[x][s]; 35 } 36 37 int main(){ 38 scanf("%d",&n); 39 for(int i=1;i<=n;i++) scanf("%d",&a[i]); 40 for(int i=2;i<maxb;i++){ 41 if(!fct[i]){ 42 for(int j=i;j<maxb;j+=i) fct[j]|=1<<pn; 43 pn++; 44 } 45 } 46 memset(rd,-1,sizeof(rd)); 47 GetAns(1,0); 48 int s=0; 49 for(int i=1;i<=n;i++){ 50 printf("%d ",b[i][s]); 51 s|=fct[b[i][s]]; 52 } 53 return 0; 54 }
Codeforces 454E/453C - Little Pony and Summer Sun Celebration
题面翻译
暮光闪闪了解到,在被流放到月球上一千年之后,邪恶的梦魇之月将会在即将到来的夏日庆典上回归。她试图警告自己的导师塞拉斯蒂娅公主,但是公主无视了她的警告,并将她派去小马镇检查庆典的准备工作。
暮光闪闪想要追踪梦魇之月的路径。可惜她并不知道具体的路径是什么样的。她只知道梦魇之月经过每个地点的次数的奇偶性。你能帮助暮光闪闪恢复出任何一条与这些信息吻合的路径吗?
小马镇可以被视为一个无重边和自环的无向图(地点是图上的点,地点之间的道路则是图上的边)。路径可以从任何地点开始或结束(也可以为空)。每一个地点可以被多次访问。路径不得经过超过$4n$个地点。
输入描述
第一行两个整数$n$和$m (2\leq n\leq10^5; 0\leq m\leq10^5)$,表示小马镇的地点个数和道路的条数。
接下来m行每行两个整数$u_i, v_i (1\leq u_i, v_i\leq n; u_i\leq v_i)$,描述一条连接$u_i$和$v_i$的道路。
再接下来一行$n$个整数:$x_1, x_2, ..., x_n (0\leq x_i\leq1)$,表示每个点必须要经过的次数的奇偶性。当$x_i=0$的时候,编号为$i$的地点必须要被经过偶数次,否则必须要被经过奇数次。
输出描述
第一行输出访问地点的数目$k (0\leq k\leq4n)$。
第二行输出$k$个整数,为按照访问顺序排序的地点编号。如果$x_i=0$,则编号为$i$的地点必须在输出的路径中出现偶数次,否则必须在输出的路径中出现奇数次。注意,由于给定的道路系统中不存在重边,因此路径上的任何两个相邻的地点必须是不同的。
如果不存在符合要求的路径,输出-1。如果存在多个可能路径,输出任意一个均可。
输入样例
样例1
3 2 1 2 2 3 1 1 1
样例2
5 7 1 2 1 3 1 4 1 5 3 4 3 5 4 5 0 1 0 1 0
样例3
2 0 0 0
输出样例
样例1
3 1 2 3
样例2
10 2 1 3 4 5 4 5 4 3 1
样例3
0
思路
这道题挺有意思的,看上去比较复杂,不过有一种很简洁明了的方式可以构造出合法的路径。
首先我们设想一下对整张图进行深度优先搜索,很显然这样的走法是不符合题意的,那么我们怎么在这个基础上,处理那些访问次数奇偶性不符合题目的点呢?
我们注意到,DFS树的叶子节点被访问了奇数次,因为访问它的路径在那里进行了“折返”,没有出现“一来一回”的情况,那么我们可以在回溯的时候简单的判断一下,刚才访问完成的那个点的奇偶性是否正确,如果不正确的话,我们就再在那个点上进行一次“折返”,使它的奇偶性改变。如此一来只有最开始访问的一个点有可能是不对的了(因为不会被在回溯的时候被处理),此时只要我们将最后一次访问操作去掉(也就是让出发点“有来无回”)即可。
但是注意,数据所给的图并不一定是联通的。当图中有两个以上的连通块存在奇数限制的点时,不存在合法路径。当图中只有一个连通块存在限制的点时,DFS必须在该连通块进行,否则无法得到满足要求的路径。为了方便起见这里DFS干脆选取了一个需要访问次数为奇数的点出发。(找不到咋办?干脆就不DFS咯,长度为0照样满足条件)
所以构造一个合法路径的方式就很明晰了:从一个需要访问次数为奇数的点出发,对整张图进行深搜,在每次回溯的时候进行判断,如果刚才访问的点的奇偶性不符合就在此进行访问,最后判断起点是否符合条件,如果不符合则删去最后一次回溯。
代码
1 #include <iostream> 2 #include <cstdlib> 3 #include <cstdio> 4 #include <cstring> 5 #include <string> 6 #include <sstream> 7 #include <cctype> 8 #include <cmath> 9 #include <algorithm> 10 #define THE_BEST_PONY "Rainbow Dash" 11 12 using namespace std; 13 const int maxn=110000; 14 15 int n,m,cnt,s=1,ans; 16 int h[maxn],nxt[maxn*2],to[maxn*2],rd[maxn],path[4*maxn]; 17 bool vis[maxn],ok=true; 18 19 void AddEdge(int x,int y){ 20 cnt++; nxt[cnt]=h[x]; h[x]=cnt; to[cnt]=y; 21 cnt++; nxt[cnt]=h[y]; h[y]=cnt; to[cnt]=x; 22 return; 23 } 24 25 void Visit(int x){ 26 path[ans++]=x; 27 rd[x]^=1; 28 return; 29 } 30 31 void DFS(int x){ 32 vis[x]=true; 33 Visit(x); 34 for(int e=h[x];e;e=nxt[e]){ 35 if(!vis[to[e]]){ 36 DFS(to[e]); 37 Visit(x); 38 if(rd[to[e]]){ 39 Visit(to[e]); 40 Visit(x); 41 } 42 } 43 } 44 return; 45 } 46 47 int main(){ 48 scanf("%d%d",&n,&m); 49 for(int i=0;i<m;i++){ 50 int x,y; 51 scanf("%d%d",&x,&y); 52 AddEdge(x,y); 53 } 54 for(int i=1;i<=n;i++){ 55 scanf("%d",&rd[i]); 56 if(rd[i]) s=i; 57 } 58 DFS(s); 59 if(rd[s]){ 60 ans--; 61 rd[s]^=1; 62 } 63 for(int i=1;i<=n;i++) 64 if(rd[i]) ok=false; 65 if(ok){ 66 printf("%d\n",ans); 67 for(int i=0;i<ans;i++) printf("%d ",path[i]); 68 } 69 else printf("-1"); 70 return 0; 71 }
Codeforces 453D - Little Pony and Elements of Harmony
题面翻译
谐律精华由代表着和谐(谐律)的六个主观方面的超自然神器组成。它们可以说是整个小马国最强大的力量。谐律精华的内部能被视为一个$n$个点的完全图,这些点被标记为$0$到$n-1$,其中$n$是2的幂,等于$2^m$。
谐律精华中的能量是在不断变化着的。据一本古书上的记载,点$u$在$i$时刻的能量($e_i[u]$)等于:
$$e_i[u]=\sum\limits_{u}e_{i-1}[v]·b[f(u,v)]$$
此处的$b[]$被称作“转换系数”,为一个包含有$m+1$个整数的数组,而$f(u,v)$则是数字$(u\ xor\ v)$的二进制表示中1的个数。
给出转换系数和0时刻的能量分布($e_0[]$)。帮助暮光闪闪预测$t$时刻的能量分布($e_t[]$)。答案可能会很大,所以输出时模除$p$。
输入描述
第一行三个整数$m$、$t$和$p(1\leq m\leq20; 0\leq t\leq10^{18}; 2\leq p\leq10^9)$。
接下来一行$n$个整数$e_0[i] (i\leq e_0[i]\leq10^9; 0\leq i<n)$。
接下来一行$m+1$个整数$b[i] (0\leq b[i]\leq10^9;0\leq i\leq m)$。
输出描述
输出$n$行,第$i$行一个整数代表$e_t[i]$模除$p$的值。
输入样例
2 2 10000 4 1 2 3 0 1 0
输出样例
14 6 6 14
思路
有待做出
代码
暂无
Codeforces 453E - Little Pony and Lord Tirek
题面翻译
提雷克大王是一只半人马,作为《我的小马驹:友谊是魔法》第四季结尾两集的主要反派登场。在“闪闪王国(上)”中,提雷克从地狱中逃出,并从小马身上吸收魔法以使自己变得更加强大。
提雷克的核心技能被称作“魔法吸收”(Absorb Mana)。它能够夺取魔法生物体内的所有魔法并将其转移到施法者的身上。
现在为了简化问题,假设有$n$只小马(编号1到$n$)。每只小马有三个属性:
- $s_i$:0时刻该小马拥有的魔法值
- $m_i$:该小马能拥有的最大魔法值
- $r_i$:该小马每单位时间能够恢复的魔法值
提雷克大王将会进行$m$次操作,每次操作可以使用三个整数进行描述:$t_i,\ l_i,\ r_i$,意思是在$t_i$时刻提雷克会对编号为$l_i$到$r_i$(包含这两个数)的小马使用魔法吸收。
输入描述
第一行包含一个整数$n\ (1\leq n\leq 10^5)$,为小马的数量。接下来$n$行每行包含三个整数$s_i,\,m_i,\,r_i$ $(0\leq s_i\leq M_i\leq 10^5;\,0\leq r_i\leq10^5)$
输出描述
输入样例
输出样例