ARC108 简要题解(A~D)
A.Sum and Product
水题,暴力即可
B.Abbreviate Fox
是我做过的一道KMP的简化版,目标串只有3个字符
原题戳这里
C.Keep Graph Connected
考虑原图的任意一颗生成树,易得原图可以简化成它,直接在树上构造即可
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <vector>
#include <queue>
#include <algorithm>
using namespace std;
const int N = 200005;
int ver[N<<1],nxt[N<<1],head[N<<1],edge[N<<1],tot;
int cnt,fa[N],n,col[N],m;
int flag = 0;
inline int read() {
int x=0,f=1;
char ch=getchar();
while(ch<'0'||ch>'9') {
if(ch=='-')
f=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9') {
x=(x<<1)+(x<<3)+(ch^48);
ch=getchar();
}
return x*f;
}
int get(int x) {
if(fa[x] == x) return x;
return fa[x] = get(fa[x]);
}
void add(int x,int y,int z) {
ver[++tot] = y;
nxt[tot] = head[x];
edge[tot] = z;
head[x] = tot;
}
void dfs(int x,int f,int prev) {
if(col[f] == prev) col[x] = (col[f]+1)%n;
else col[x] = prev;
for(int i = head[x];i;i = nxt[i]) {
int y = ver[i];
if(y == f) continue;
dfs(y,x,edge[i]);
}
}
int main () {
n = read();m = read();
for(int i = 1;i <= n;i++) fa[i] = i;
for(int i = 1;i <= m;i++) {
int u,v,w;
u = read();v = read();w = read();
if(flag) continue;
// cout<<"fuck";
int fx = get(u),fy = get(v);
// cout<<fx<<" "<<fy<<" "<<i<<endl;
if(fx == fy) continue;
add(u,v,w);add(v,u,w);
fa[fy] = fx;
++cnt;
if(cnt == n-1) {
flag = 1;
continue;
}
}
col[1] = 1;
dfs(1,0,0);
for(int i = 1;i <= n;i++) {
if(col[i] == 0) col[i] = 1;
printf("%d\n",col[i]);
}
return 0;
}
D.AB
分类讨论
不妨设\(c_{AB} = A\),另外一种情况类似
首先,当\(c_{AA} = A\)时,最后的串只可能是\(AAA...B\),答案为\(1\)
当\(c_{AA} = B\),再次分类讨论
这时,最终的串一定是以A开头,AB结尾的串
当\(c_{BA} = B\) 时,任何一个都能被构造出来,答案为\(2^{n-3}\)
当\(c_{BA} = A\) 时,一个串不含\(BB\)这样的子串是它能被构造出来的充要条件,答案为\(f_{n-1}\),其中\(f\)为斐波那契数列
解释一下为什么是\(f_{n-1}\),
设\(dp_{i,A}\)表示当长度为\(i\),结尾为\(A\)的合法串的个数
显然有
\(dp_{k,A} = dp_{k-1,A} + dp_{k-1,B}\)
\(dp_{k,B} = dp_{k-1,A}\)
将第二个式子带入第一个式子,得
\(dp_{k,A} = dp_{k-1,A} + dp_{k-2,A}\)
答案为\(dp_{n-1,A}\)

浙公网安备 33010602011771号