发现已经错过最美的花期|

ricky_lin

园龄:3年8个月粉丝:11关注:2

【题解】gym103495 (2021 JSCPC)

A. Spring Couplets

就是判断是否满足一下条件:

  • 对联对位上平下仄、上仄下平
  • 第一句对联的最后一个是仄

模拟即可。

code:

#include<bits/stdc++.h>
using namespace std;
const int NN = 30;
int T,n;
int a[NN],b[NN];
inline int read(){
register char c = getchar();
register int res = 0;
while(!isdigit(c)) c = getchar();
while(isdigit(c)) res = res * 10 + c - '0',c = getchar();
return res;
}
void solve(){
n = read();
for(int i = 1; i <= n; ++i) a[i] = read();
for(int i = 1; i <= n; ++i) b[i] = read();
for(int i = 1; i <= n; ++i)
if((a[i] <= 2 && b[i] <= 2) || (a[i] >= 3 && b[i] >= 3)) return puts("NO"),void(0);
if(a[n] <= 2) return puts("NO"),void(0);
else return puts("YES"),void(0);
}
int main(){
T = read();
while(T--){
solve();
}
}

B. Among Us

这道题我们考虑 k=8,显然需要用到状压。

我们考虑有两个杀手,我们可以对每个杀手分别求一遍,然后合并起来。

对于一个杀手,我们设 fu,S 表示当前杀手在 u 节点,杀了集合 S 的人需要的最短时间。

如何转移?我们考虑使用 dijstra 进行转移。

转移分成两种:

  • 待在一个房间干掉下一个人
  • 去其他房间

code:
还没有~~~

C. Magical Rearrangement

这道题显然从高位到低位,从小到大贪心即可。

当然需要特判只有一个 0 的情况(因为这个我 WA 了两发)

code:

#include<bits/stdc++.h>
using namespace std;
const int NN = 1e5 + 8;
int T;
int a[NN];
inline int read(){
register char c = getchar();
register int res = 0;
while(!isdigit(c)) c = getchar();
while(isdigit(c)) res = res * 10 + c - '0',c = getchar();
return res;
}
void solve(){
int sum = 0;
for(int i = 0; i <= 9; ++i) sum += (a[i] = read());
if(sum == 1 && a[0] == 1){
return puts("0"),void(0);
}
for(int i = 0; i <= 9; ++i){
if((sum + (i != 0)) / 2 < a[i]) return puts("-1"),void(0);
}
for(int i = 1,pre = 0; i <= sum; ++i){
int x = -1;
for(int j = 0; j <= 9; ++j){
if(pre == j) continue;
if((sum - i + 2) == 2 * a[j]){x = j;break;}
}
if(x == -1){
for(int j = 0; j <= 9; ++j){
if(pre == j) continue;
if(a[j] != 0){x = j;break;}
}
}
printf("%d",x);
--a[x];
pre = x;
}
puts("");
}
int main(){
T = read();
while(T--){
solve();
}
}

D. Pattern Lock

我们考虑比较正常的想法就是我们可以发现以锯齿状的方式可以一次性将一个 2×n 的图解决,如下图:

我们考虑怎么扩展到 n×m(n%2==0),我们只需要将锯齿形改成下图即可:

可以发现上图都是小于 90 的。

现在我们就可以构造所有 n,m 中有一个是偶数的矩形,现在我们考虑如何构造 n,m 全是奇数的矩形:

我们发现,挖去一个 3×3 的矩形之后就会拆成两个边长一奇一偶的矩形,如下图:

然后上图中的浅绿色的线是拿来衔接矩阵之间的线,红色是锯齿形解决 偶×奇 时上面破坏锯齿结构的横穿的线

至于左上角的 3×3 的矩形,可以构造一个自己喜欢的(其实解决边长有一个偶数的矩形也不止上面一种方法,读者可以自行探索)。

code:

#include<bits/stdc++.h>
using namespace std;
int n,m;
int addx,addy;
bool tag;
void print(int x,int y){
x += addx;y += addy;
if(tag) printf("%d %d\n",y,x);
else printf("%d %d\n",x,y);
}
void solve1(int n,int m,int op = 1){
if(m == 2){
for(int i = 1; i <= n; ++i){
print(i,1);
print(i,2);
}
return;
}
for(int i = 1; i <= n / 2; ++i){
if((i & 1) == op){
print(i*2-1,m);
print(i*2,1);
print(i*2-1,1);
for(int j = 2; j <= m-1; ++j){
print(i*2,j);
print(i*2-1,j);
}
print(i*2,m);
}
else{
print(i*2-1,1);
print(i*2,m);
print(i*2-1,m);
for(int j = m-1; j >= 2; --j){
print(i*2,j);
print(i*2-1,j);
}
print(i*2,1);
}
}
}
void solve2(int n,int m){
if(n > m) swap(n,m),tag ^= 1;
if(((m-3) % 4) == 0){
print(1,1);print(2,3);print(3,1);
print(3,2);print(2,1);print(1,3);
print(2,2);print(1,2);print(3,3);
addx = 3;addy = 0;
tag ^= 1;
solve1(m-3,3,0);
tag ^= 1;
addx = addy = 0;
}
else{
print(3,1);print(2,3);print(1,1);
print(1,2);print(2,1);print(3,3);
print(2,2);print(3,2);print(1,3);
addx = 3;addy = 0;
tag ^= 1;
solve1(m-3,3,1);
tag ^= 1;
addx = addy = 0;
}
addx = 3,addy = 0;
solve1(n-3,m,0);
}
int main(){
scanf("%d%d",&n,&m);
if(m % 2 == 0) swap(n,m),tag = 1;
if(n % 2 == 0){
solve1(n,m);
}
else{
solve2(n,m);
}
}

E. Stone Ocean

我们首先把期望转化为 权值和 / 总方案数。

这道题我们考虑还是状态压缩,设 fS 表示将集合 S 中的字符串从外向内填入回文串的方案数。

因为当 |S|mod2==0 时状态才有意义,可以证明状态数是 1.618n 的。

至于代码实现可以使用队列将每一层可以到达的状态找出来,按层转移。

code:

还没有QAQ~~~

F. Jumping Monkey II

我们考虑,只有子树内的 LIS 是好求的,我们可以使用 启发式合并/线段树合并

我们考虑如何去求一个点父亲方向的 LIS,考虑 淀粉质,我们可以将一个父亲方向的路径按分治中心分成 logn 段。

然后对每个分治中心,维护其每棵子树的最长下降子序列的 DP 数组,将这些 DP 数组合并到分治中心,再贡献给每棵子树的每个结点

时间复杂度 O(nlogn)

code:

还没有QAQ~~~

G. Five Phases

我们考虑生成函数,由题可以得到答案是下面这个式子:

[vawbxcydze](v+w+x+y+z+1v+1w+1x+1y+1z+vwx+wxy+xyz+yzv+zvw+1vwx+1wxy+1xyz+1yzv+1zvw+vwy+wxz+xyv+yzw+zvx+yvw+zwx+vxy+wyz+xzv+1vwxyz+vwxyz)k

然后我们考虑化简之后可以变成:

[vawbxcydze][(1+vw)(1+wx)(1+xy)(1+yz)(1+zv)vwxyz]k

然后我们设 vw,wx,xy,yz,zv 的次数为 o,p,q,r,s,那么可以得到下面的方程组:

{a=s+okb=o+pkc=p+qkd=q+rke=r+sk{o=bc+de+a+k2p=cd+ea+b+k2q=de+ab+c+k2r=ea+bc+d+k2s=ab+cd+e+k2

答案就是 (ko)(kp)(kq)(kr)(ks)

code:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int NN = 1e5 + 8,MOD = 998244353;
ll fac[NN],inv[NN];
inline int read(){
register char c = getchar();
register int res = 0,flag = 1;
while(!isdigit(c)) flag = c == '-' ? -1 : flag,c = getchar();
while(isdigit(c)) res = res * 10 + c - '0', c = getchar();
return res*flag;
}
inline ll ksm(ll x,ll k){
ll res = 1;
while(k){
if(k&1) res = res * x % MOD;
x = x * x % MOD;
k >>= 1;
}
return res;
}
void init(){
fac[0] = 1;
for(int i = 1; i < NN; ++i) fac[i] = fac[i-1] * i % MOD;
inv[NN-1] = ksm(fac[NN-1],MOD - 2);
for(int i = NN-1; i >= 1; --i) inv[i-1] = inv[i] * i % MOD;
}
inline ll binom(ll n,ll m){
if(m % 2 != 0) return 0;
else m /= 2;
if(m > n || n < 0 || m < 0) return 0;
return fac[n] * inv[m] % MOD * inv[n-m] % MOD;
}
void solve(){
ll a = read(),b = read(),c = read(),d = read(),e = read(),k = read();
ll o,p,q,r,s;
o = (b-c+d-e+a+k);
p = (c-d+e-a+b+k);
q = (d-e+a-b+c+k);
r = (e-a+b-c+d+k);
s = (a-b+c-d+e+k);
printf("%lld\n", binom(k,o)
* binom(k,p) % MOD
* binom(k,q) % MOD
* binom(k,r) % MOD
* binom(k,s) % MOD);
}
int main(){
init();
int T = read();
while(T--){
solve();
}
}

H. Reverse the String

你考虑字典序最小的字符串显然就是排序之后的字符串。

我们考虑翻转字符串的左端点应该在哪里,显然就是原字符串和排序之后的字符串的第一个不同的位置就是翻转的左端点。

我们现在需要找到最优的翻转的右端点,我们考虑 O(n2) 做法就是对于每个右端点都跑一边,然后暴力找最优解。

我们考虑我们可以加速这个过程,我们考虑如何快速比较两个字符串的大小,显然可以通过 二分+Hash 解决这个问题。

code:

还没有QAQ~~~

I. Fake Walsh Transform

考虑这道题,我们发现 02m1 的亦或和是 0,那么我们只需要不亦或 n 即可。

当然当 n/m0/1 的时候有一些特殊情况需要特判一下。

J. Anti-merge

最后应该到达的状态显然是:

  • 对于任意单元格内容,将不添加标签看成 0 号标签。对于一个单元格,由单元格内容和单元格标签组成的 pair 对应该与它四连通的所有单元格互不相同。

考虑黑白棋盘染色,可知最少所用颜色数不超过 1

对于方案的求解,可以考虑使用 BFS,从每个位置开始对 pair 相同的单元格区域进行这种黑白染色,取黑白颜色数较少的颜色填充标签即可。

K. Longest Continuous 1

我们可以进行 打表 发现每个长度第一次出现的位置都是 111111 + 100000 的形式。

我们考虑如何证明:

我们发现连续的 1 只能由两个数字构成,因为两个数字一定是一奇一偶

  • 若前奇后偶,那么可以发现最早的一定是上面的情况
  • 若前偶后奇,那么最优一定会是这样:11110111 + 11111000 我们会发现它一定不能超过一个 01 串的长度,显然是不优的

我们考虑设 f(x) 表示 长度为 x 的连续的 1 第一次出现需要的长度,那么有如下递推式:

f(1)=2f(x)=f(x1)+x(2x12x1+1)=f(x1)+x(2x2x1)

然后我们就可以预处理出 f(130),之后随便 爆扫 或者 二分答案 即可。

L. Tree Game

我们首先需要判断无解,这是很好判断的,就是忽略可以填任意数的位置,模拟一遍即可

然后我们设 fu 表示以 u 为根的子树内正确排序的方案数,可以得到下面的转移方程:

fu=(cnt0)!fv

cnt0 即为操作 u0 的个数。

为什么是 (cnt0)! 呢?为什么不用确定哪个数是哪个呢?

我们考虑当最后的操作完之后,我们的每个 0 所在位置就是它应该填的数,所以我们只需要将 0 交换到应该的位置上。

因为前面已经判过了无解,所以说确定的数的位置是确定的,只有 0 的位置不确定,无论怎么填 0 的顺序在方案的合法性上都是等价的。

然后这道题就完了

最后这套题就完了~

有一些题目的代码有时间再补,没时间就咕咕咕~~~

posted @   ricky_lin  阅读(106)  评论(1编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起
  1. 1 有我 周深
有我 - 周深
00:00 / 00:00
An audio error has occurred.

作词 : 唐恬/闫光宇

作曲 : 钱雷

编曲 : 赵兆/付虹宇

制作人 : 赵兆

出品 : 共青团中央宣传部

版权 : 中国青少年新媒体协会

制作单位 : 能量悦动音乐

发行单位 : 银河方舟StarNation

出品人 : 郭峰

总监制 : 汤杰

总策划 : 钟亚楠

总统筹 : 金慧子

音乐监制 : 李天鹏/李三木

制作执行 : 张不贰/高聪怡

项目宣发 : 肖健/张国党/孙小千/戴胤/孙雯璟

音乐推广 : 代诗琪/杜思潮/马越/程铁峰/傅之豪

钢琴 : 赵兆

吉他 : 伍凌枫

贝斯 : 韩阳

鼓 : 武勇恒

合唱设计 : 赵兆

合唱 : 凡尔赛合唱团

人声录音 : 耿潇微

人声录音室 : 55TEC Studio Beijing

配唱 : 徐威@52Hz Studio (Shanghai)

混音 : 李游(小骷髅)@55TEC Studio Beijing

海报 : 格子

特别鸣谢 : 周深工作室

世界问 你是谁 来自哪 请回答

爱什么 梦什么 去何方 请回答

答案有 一百年的时光

我来自 硝烟中 课桌旁 的太阳

我来自 硝烟中 课桌旁 的太阳

他和她 宣的誓 迎的仗

来自那 燃烧的 和我一样 的年华

来自世间 一对平凡的夫妻 身旁

来自世间 一对平凡的夫妻 身旁

来自昨天 谁以青春赴万丈 理想

我是寸土 不让的 家乡啊

我是绝不 低头的 倔强啊

接过万千热血 的初衷

当有对答世界 的音量

要怎么形容明天 像我一样

要怎么形容明天 像我一样

承风骨亦有锋芒 有梦则刚

去何方 去最高 的想象

前往皓月星辰 初心不忘

那未来如何登场 有我担当

那未来如何登场 有我担当

定是你只能叫好 那种辉光

护身旁 战远方 有我啊

我的名字就是 站立的地方

Wu~

我的样子 就是 明天的模样

我是朝阳 落在乡间听书声 朗朗

我是朝阳 落在乡间听书声 朗朗

我是屏障 为谁挡一程厄运 的墙

我要一生 清澈地 爱着啊

我要长歌 领着风 踏着浪

朝着星辰大海 的方向

当有对答世界 的音量

要怎么形容明天 像我一样

要怎么形容明天 像我一样

承风骨亦有锋芒 有梦则刚

去远方 去最高 的想象

前往皓月星辰 初心不忘

那未来如何登场 有我担当

那未来如何登场 有我担当

定是你只能叫好 那种辉光

护身旁 战远方 有我啊

一生骄傲为我 站立的地方

Wu~

我的样子 就是 中国的模样

Wu~~~ Wu~~~

当炬火 去化作那道光

“谨以此歌献给一代代不负时代重托的中国青年”

“谨以此歌献给一代代不负时代重托的中国青年”