The 2021 ICPC Asia Shenyang Regional Contest
solo 七题罚时 738 打到金尾了,但是这个 G 和 I 也应该是自己能做出来的。G 找了若干性质确实转化到最后一步了。但本应该搞出的 dp 没有想到。G 和 M 感觉都有点降智。而 I 则是被复数吓到了。有点菜。
B:拆位,扩展域并查集。E:签到。F:签到。
G(补题)
题解
先转化到,确定一个颜色序列,再选出一个子序列,颜色是按顺序出现的如 aaabbbbcdd
这样子,满足出现过的字符都出现了的前提下,先最大化第一种字符出现次数,再最大化第二种......
确定颜色序列而颜色数只有 ,所以想到状压 dp 令 表示填了 集合中的颜色,并且已经满足最大化的限制,当前选到了哪里。当它后面接了一个 之后我们需要保证在后缀中 都出现的前提下 尽可能多,所以对每个集合预处理出最靠后的后缀使得这个集合中颜色均出现,并预处理出子序列自动机即可得到 后面跟了一个 转移到的位置。
还要保证从前往后最大化出现次数,把集合大小 的放在一起,按照 从小往大去转移,这样对于每个 来说仅做出现次数最大的那些转移即可。现在时间复杂度是 .
H
题解
想得还挺顺利,一步步都想到了。
首先一个连通块的边数是偶数一定能全选完,这是一个经典的树上匹配问题,自底向上贪心选的时候先把挂在这个点上的所有边两两匹配完,如果匹配不完就留连到父亲的那条边就行。
现在 是奇数,如果删掉的边不是割边可以直接更新答案。然后发现割边不会删掉 ,若删掉了 中的两条割边形成了 这是三个连通块,其中 边数均为偶数,那么不删这两条割边会更优。于是枚举删掉哪条割边,判断是否满足条件满足条件就更新答案,这样就行了。
I(补题)
题解
没救了。复数关于四则运算是封闭的,所以把一个复数看成一个未知数就行啊啊啊。既然保证有唯一解,那就尝试先设出来某个数是 还是 两种情况(如果是非 复数可以直接同时除掉它本身得到 )然后前者可以直接求出来,后者三元三次方程就高消一下。
J
题解
定位是简单题,但卡了许久。发现只和差有关所以做一遍 bfs 求出 到所有状态的最小步数就行。
L
题解
很快啊,一眼秒了。
问题就是计算完美匹配数,匹配要求在树上不能相邻。容斥钦定 相邻的,剩余的任意匹配方案数,乘上 贡献到答案里。于是 dp 表示 子树内钦定了 对,其中 是否已被钦定,方案数是多少。树形背包复杂度 .
M
题解
可能真是做着做着累了就思考不动了。
尝试按字典序遍历出所有子串?endpos 相同的一个等价类里面的子串确实只有字典序最大的那个有用对吧。把 SAM 建出来,在 DAWG 上优先走较大的边去遍历 DAWG,打上它是被第几个遍历到的时间戳,如果有一个节点被遍历过了就不再走了。
确定前缀 的答案的时候,它在 parent 树上的根链上最早被遍历到的串即为答案。
D(补题)
题解
?这什么 shaber 板子题
先二分答案,然后分层图拆点跑最大流就行。
C(补题)
题解
打牌分讨题。
copy 是能够复制 copy 的,所以有 water 并且 copy 就能造成无限伤害。有水人的情况下 copy 复制成火球再把火球打出去能造成 点伤害。
策略是:
- 没有 waterman 在场上:一直留着牌直到有 water 就打 water,或者手里的 fire 和 copy 就能赢。
- 有 waterman 在场上:
- water 和 fire 抽到直接打出去。
- 有 2 张 copy 直接赢(手中的以及打出去的)
- 有 1 张 copy:等到打过 fire 的时候再复制为 fire 打出去。
按照有无 water 分,假如枚举了 water 是在第几个抽到的,那么发现前半部分的信息只需得知是否有 fire,以及 copy 是 ;而后半部分的信息只需要得知当前 hp 剩余多少,fire 有无打过,copy 是手里 张 / 手里 张 / 已打过 张。
于是前半部分一个 dp 算,后半部分一个 dp 算,枚举第几个抽到 water 算下答案。还有一个问题是根本就不会进行到后半部分,一种情况是到 张抽完之后有 fire,由于 fire 和 copy 都能造成 2 的伤害所以直接赢;如果全是 copy,那么不断抽直到抽到 fire/water 就能赢,由于一次抽到 fire/water 的概率是 ,那么这里的期望步数就是 .
具体细节就看看代码。
const int N=200010;
const int i3=332748118;
int f[N][2][3];//摸了n张牌, 0/>=1张fire, 0/1/>=2张copy
int g[N][2][3];//water打过, 怪物血量为k, 用了0/>=1张fire, 手里0张/手里1张/打出一张copy
int dfs(int k,int f,int c){
if(k<=0)return 0;
if(c==1&&k<=2)return 0;
if(c==1&&f==1&&k<=4)return 0;
if(~g[k][f][c])return g[k][f][c];
int &now=g[k][f][c];now=1;
//water
cadd(now,1ll*i3*dfs(k-1,f,c)%mod);
//fire
if(c==1)cadd(now,1ll*i3*dfs(k-7,1,2)%mod);
else cadd(now,1ll*i3*dfs(k-3,1,c)%mod);
//copy
if(c==0){
if(f)cadd(now,1ll*i3*dfs(k-4,1,2)%mod);
else cadd(now,1ll*i3*dfs(k,0,1)%mod);
}
return now;
}
int n;
signed main(){
read(n);
f[0][0][0]=1;
for(int i=0;i<=(n+1)/2;i++)
for(int j=0;j<=1;j++)
for(int k=0;k<=2;k++){
cadd(f[i+1][min(j+1,1)][k],1ll*i3*f[i][j][k]%mod);
cadd(f[i+1][j][min(k+1,2)],1ll*i3*f[i][j][k]%mod);
}
int ans=0;
memset(g,-1,sizeof(g));
for(int i=0;i<=(n-1)/2;i++){//在i+1张牌抽到water
cadd(ans,1ll*i3*f[i][0][0]%mod*(i+1+dfs(n,0,0))%mod);
cadd(ans,1ll*i3*f[i][0][1]%mod*(i+1+dfs(n,0,1))%mod);
cadd(ans,1ll*i3*f[i][0][2]%mod*(i+1)%mod);
cadd(ans,1ll*i3*f[i][1][0]%mod*(i+1+dfs(n-3*i,1,0))%mod);
cadd(ans,1ll*i3*f[i][1][1]%mod*(i+1+dfs(n-3*(i-1)-4,1,2))%mod);
cadd(ans,1ll*i3*f[i][1][2]%mod*(i+1)%mod);
}
for(int i=0;i<3;i++){
cadd(ans,1ll*f[(n+1)/2][0][i]*((n+1)/2+3ll*499122177%mod)%mod);
cadd(ans,1ll*f[(n+1)/2][1][i]*((n+1)/2)%mod);
}
cout<<ans<<'\n';
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?