题面

对于字符串 \(s\) 定义一个变换 \(f(s)\) 表示, \(\forall 1\le k\le \lfloor|s|/2\rfloor\) ,将 \(s\) 中从后往前第 \(k\) 个字符插入从前往后第 \(k\) 个字符和第 \(k+1\) 个字符之间后得到的字符串,例如 \(\texttt{abcdef}\) 变换后得到 \(\texttt{afbecd}\) .

现在给出用 \(f(s)\) 变换过 \(k\) 次以后的字符串(即执行 \(k\) 次 \(s:=f(s)\)),求变换之前的字符串 .

(别骂我,这是原题面)

\(3\le |s|\le 10^3, 1\le k\le 10^9\) .

置换

这里没有群论

这里没有群论 .

这里的置换是狭义的,正经置换看 OI-Wiki(内含 Burnside,慎入)

置换

一个置换 \(p\) 定义为一个排列,置换相当于一个运算,将原来在位置 \(i\) 的东西变到位置 \(p_i\) .

置换的乘法(复合)

你对一个东西施加置换 \(p\) 然后施加置换 \(q\),就相当于施加 \(p\circ q\) .

显然新的置换 \(h=p\circ q\) 由下式直接表示:

\[h_i=q_{p_i}
\]

置换乘法的单位元

恒等置换 \(id\) 定义为 \(id_i=i\) .

显然任何置换 \(p\) 满足 \(p\circ id = id \circ p\),于是 \(id\) 就是 \(\circ\) 的单位元 .

置换乘法的结合律

结合律:

\[p\circ q\circ r = p\circ (q\circ r)
\]

为啥?

这里我们用函数表示下标,因为下标实在太多了 .

\[(p\circ q\circ r)(i) = p(q(r(i))) = p((q\circ r)(r) = (p\circ (q\circ r))(i)
\]

Q.E.D. 是不是很显然 .

置换快速幂

有单位元,有结合律,显然可以 \(\log\) 快速幂吧 .

置换求乘法逆

显然求逆就是把置换逆过来了(类似反函数?)(从施加的角度看,真的很显然)

原来是 \(i\to p_i\),现在就是 \(p_i\to i\) .

直接模拟算就完了 .

真题解

题目要求的 \(f\) 可以看做一个置换 \(p\) .

于是 \((p^{k})^{-1}\) 就是我们要对字符串 \(s\) 施加的置换 .

直接算出来,时间复杂度 \(O(|s|\log k)\) .

一种可能的代码实现

因为求逆可以先求也可以后求甚至可以直接拿眼看出来,所以可能的代码实现有很多 .

这里是先快速幂再求逆,应该是好理解的 .

// 增加了注释
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <ctime>
#include <vector>
#include <queue>
#include <cmath>
#include <map>
#include <set>
#include <bitset>
#include <cassert>
using namespace std;
const int N = 1555;
int k;
string s;
struct perm // 置换
{
perm(int x=1){n=x; for (int i=1; i<=x; i++) a[i] = i;} // 初始化为恒等置换
int operator [](const unsigned& id)const{return a[id];}
int& operator [](const unsigned& id){return a[id];} // 元素
perm operator * (const perm& rhs)const // 乘法
{
assert(n == rhs.n);
perm x(n);
for (int i=1; i<=n; i++) x[i] = rhs[a[i]];
return x;
}
perm& operator *= (const perm& rhs){return *this = *this * rhs;}
perm inv() // 求逆
{
perm ans(n);
for (int i=1; i<=n; i++) ans[a[i]] = i;
return ans;
}
inline void prt() // debug
{
for (int i=1; i<=n; i++) printf("%d ", a[i]);
puts("");
}
inline size_t size()const{return n;}
private:
int n, a[N];
};
perm qpow(perm a, int n) // 快速幂
{
perm ans(a.size());
while (n)
{
if (n&1) ans *= a;
a *= a; n >>= 1;
} return ans;
}
perm create(int n) // 生成题目说的变换 f
{
perm ans(n);
int ptr1 = 1, ptr2 = n, cc = 0;
while (ptr1 <= ptr2){ans[++cc]=ptr1; if (cc<n) ans[++cc]=ptr2; ++ptr1; --ptr2;}
return ans;
}
int main()
{
scanf("%d", &k);
cin >> s; int l = s.length(); s = "$" + s;
perm ans = qpow(create(l), k).inv();
for (int i=1; i<=l; i++) putchar(s[ans[i]]); // 对 s 施加置换
puts("");
return 0;
}

关于循环节做法

看起来这个东西有循环节?打了一发直接过了,出题人可真 sb

实际上我们可以证明这个东西有循环节且循环节是不大于 \(|s|\) 的 .

从置换的角度考虑,如果 \(i\) 能到 \(p_i\) 就连一条 \(i\to p_i\) 的有向边 .

\(n\) 个点 \(n\) 条边显然可以构成一个内向基环树森林,运算相当于在图上走一次,一直走肯定能走到环上 .

这说明任何置换 \(p\) 的方幂都是有循环节的 .

然而这题里的 \(p\) 更加特殊:

咕咕咕

Str 真题解(置换)的更多相关文章

  1. csps-s模拟测试60嘟嘟噜,天才绅士少女助手克里斯蒂娜,凤凰院凶真题解

    题面:https://www.cnblogs.com/Juve/articles/11625190.html 嘟嘟噜: 约瑟夫问题 第一种递归的容易re,但复杂度较有保证 第二种适用与n大于m的情况 ...

  2. 对于JavaScript对象的prototype和__proto__的理解

    一.Object和Function的关系: 刚学JavaScript的时候,看书上说JavaScript中万物皆对象,而javascript中的其他对象都是从Object继承而来,包括内置对象.瞬间觉 ...

  3. [Poj3128]Leonardo's Notebook

    [Poj3128]Leonardo's Notebook 标签: 置换 题目链接 题意 给你一个置换\(B\),让你判断是否有一个置换\(A\)使得\(B=A^2\). 题解 置换可以写成循环的形式, ...

  4. python3+django2 开发易语言网络验证(中)

    第四步:网络验证的逻辑开发 1.将model注册到adminx.py中 1.在apps/yanzheng目录下新建admin.py 文件,添加代码: import xadmin from xadmin ...

  5. 【原】Java学习笔记022 - 字符串

    package cn.temptation; public class Sample01 { public static void main(String[] args) { // 字符串 // 定义 ...

  6. PMP备考资料和备考经验分享(基于PMP第六版)

    之前有不少小伙伴私信我说,你PMP考过了,有没有报班呢,有没有自己看的资料,有没有一些经验分享,今天在这里,就统一给大家分享一下,以便大家备考和学习PMP. 先说我自己的情况,我本身是从事项目管理的, ...

  7. [POI2007]EGZ-Driving Exam

    能到达所有路的充要条件是能到达左右两端的路 用vector反向建边对每条路左右分别求个最长不上升子序列 预处理出每条路向左向右分别需要多建多少路才能到达最左端和最右端 然后跑个\(\Theta(n)\ ...

  8. qsc round#2 喵哈哈村的排队(本辣鸡想七想八的,特写此博文给自己一个提醒)

    该oj是qsc自己写的比赛,友情链接:http://qscoj.cn/ 喵哈哈村的排队 发布时间: 2017年2月26日 16:13   最后更新: 2017年2月26日 16:14   时间限制: ...

  9. Ruby Regexp类

    正则表达(Regexp)类 更新:2017/06/18 改变[]集合的表格大小 80% ---> 100%  定义 正则表达: 和字符串匹配的模式(pattern)的写法 正则表达(Regexp ...

随机推荐

  1. Redis设计与实现2.2:数据持久化

    数据持久化 这是<Redis设计与实现>系列的文章,系列导航:Redis设计与实现笔记 RDB持久化 RDB 持久化功能所生成的 RDB 文件是一个经过压缩的二进制文件,通过该文件可以还原 ...

  2. 【freertos】010-消息队列概念及其实现细节

    目录 前言 10.1 消息队列概念 10.2 消息队列的数据传输机制 10.3 消息队列的阻塞访问机制 10.4 消息队列使用场景 10.5 消息队列控制块 10.5.1 队列控制块源码 10.5.2 ...

  3. CentOS7及以下版本安装禅道

    由于是CentOS7以及以下系统,禅道已经集成了 Apache Nginx Mysql 服务,不需要我们再次安装搭建,我们只进行解压使用就好: 一.进行下载安装 1.在终端命令中输入以下命令确认系统是 ...

  4. 数据库常用DDL语句

    一.创建表 CREATE TABLE TABLE_NAME( #create table 表名 ID INT(4) PRIMARY KEY, #字段名 数据类型 完整性约束条件 NAME VARCHA ...

  5. NB-IoT无线通信模块与Lora无线通信协议技术分析与前景展望

    物联网的快速发展对无线通信技术提出了更高的要求,专为低带宽.低功耗.远距离.大量连接的物联网应用而设计的LPWAN(low-power Wide-Area Network,低功耗广域网)也快速兴起.物 ...

  6. 如何优化PlantUML流程图(时序图)

    这篇文章用来介绍,如何画出好看的流程图. 1. 选择合适的组件 1.1 plantuml官方提供的组件 1.2 加载图片 1.2.1 加载本地图片 1.2.2 加载网络图片 1.2.3 图片资源 2. ...

  7. Acwing 1927 自动补全(知识点:hash,二分,排序)

    读完题目第一想法是trie树 ,不过好像没怎么做过trie树的题,看y总给的知识点是二分排序,所以就有了如下思路: 但是但是,看完其他题解之后才坚定了我的想法,原来真的是这样排序,暴力啊! 具体步骤 ...

  8. 皓远的第一次博客作业(pta题目集——1-3)

    题目集总结: 前言: 一. 知识点运用: ①    Java入门的基础语法(循环,判断,字符串,数组等等),Java的基础类运用,类与对象关系调用,类间关系(聚合). ②    引(类与对象): 对象 ...

  9. 不同network中的两个docker容器

    1. 创建docker网络 docker network create --subnet 172.18.0.1/16 test docker network ls 2. 创建两个容器指定docker ...

  10. 细说GaussDB(DWS)复杂多样的资源负载管理手段

    摘要:对于如此多的管控功能,管控起来实际的效果到底如何,本篇文章就基于当前最新版本,进行效果实测,并进行一定的分析说明. 本文分享自华为云社区<GaussDB(DWS) 资源负载管理:并发管控以 ...