【Atcoder】AGC027 B-F简要题解

B.Garbage Collector

假设机器某次出发到回到 0 0 0的过程中收集了 a a a个垃圾,最优过程必然是先走到最远的垃圾处拿起来,再在往回走的过程中依次拿起剩下 a − 1 a-1 a1个垃圾。

f ( i , j ) f(i,j) f(i,j)表示从左到右第 i i i个垃圾在同一组中在第 j j j次被拿起的花费:
f ( i , j ) = { 5 x i + 2 X    ( j = 1 ) ( 2 j − 1 ) x i + X    ( j > 1 ) f(i,j)=\left\{\begin{matrix} 5x_i+2X\ \ (j=1)\\ (2j-1)x_i+X\ \ (j>1) \end{matrix}\right. f(i,j)={5xi+2X  (j=1)(2j1)xi+X  (j>1)

考虑枚举划分出的组数 k k k,显然最远的 n k \frac nk kn作为每组内最先拿的垃圾最优,于是每相邻 n k \frac nk kn个分别分到每个组。算一下总贡献取 min ⁡ \min min即可。复杂度是调和级数的 n ln ⁡ n n\ln n nlnn


C.ABland Yard

可行解的图一定是一个环,满足环上每一个点都有 A , B A,B A,B的出边。
所以类似于拓扑排序,每次删去没有 A / B A/B A/B出边的点即可。


*D.Modulo Matrix

构造 m o d = 1 mod= 1 mod=1的情况:

如果没有限制所有位置数不同,可以将网格黑白染色,所有黑格值为 n + 1 n+1 n+1,白格为 n n n
(好吧我知道其实更容易想到 2 , 3 , 4 , . . . 2,3,4,... 2,3,4,...,但是要贪心在更小的权值区间内取得更大的矩阵…)

加上限制后同理,假设黑格比它相邻的白格都大,则值为它相邻的白格值的 l c m + 1 lcm +1 lcm+1,且所有黑格之间互不影响。

用不同的质数填充所有正/反对角线即可,每个白格的值为两条对角线上质数的乘积。


**E.ABBreviate

a a a看做 1 1 1 b b b看做 2 2 2,序列在 ( m o d 3 ) \pmod 3 (mod3)意义下保持不变。

求序列的前缀和 S S S,那么可以构造出的所有序列的前缀和都是 S S S的子序列,DP即可。

把每个 S [ i ] = S [ n ] ( i < n ) S[i]=S[n](i<n) S[i]=S[n](i<n)后面存在两个相邻字符相同的情况或者 f [ i ] f[i] f[i]计入答案,最后 + f [ n ] +f[n] +f[n]即可。

code from DZYO

#include 
using namespace std;

const int N=1e5+50, mod=1e9+7;
inline void add(int &x,int y) {x=(x+y>=mod) ? (x+y-mod) : (x+y);}

char t[N]; 
int n,ans,s[N],f[N],pre[N][3],fir[N];

int main() {
	scanf("%s",t+1); n=strlen(t+1);
	for(int i=1;i<=n;i++) s[i]=(s[i-1]+t[i]-'a'+1)%3;
	pre[0][0]=pre[0][1]=pre[0][2]=-1;
	for(int i=1;i<=n;i++) {
		pre[i][0]=pre[i-1][0];
		pre[i][1]=pre[i-1][1];
		pre[i][2]=pre[i-1][2];
		pre[i][s[i-1]]=i-1;
	}
	for(int i=1;i<=n;i++) {
		fir[i]=fir[i-1];
		if(t[i]==t[i-1]) fir[i]=i;
	}
	f[0]=1;
	for(int i=1;i<=n;i++) {
		int pos=fir[i]-1;
		f[i]=f[i-1];
		int val=(t[i]=='a') ? 2 : 1;
		if(~pos) {
			pos=pre[pos][(s[i]-val+3)%3];
			if(~pos) add(f[i],f[pos]);
		}
		if(!s[i] && i!=n) add(f[i],1);
	} 
	if(!fir[n]) for(int i=1;i<n;i++) if(!s[i]) add(f[n],mod-1);
	cout<<f[n]<<'\n';
}

F.Grafting

分两种情况讨论:

  • A → B A\to B AB存在不动点。 O ( n ) O(n) O(n)枚举不动点 i i i,以 i i i为根,对于点 x ( x ≠ i ) x(x\neq i) x(x̸=i),若 x x x A A A中的父结点为 y y y,在 B B B中的父结点为 z ( y ≠ z ) z(y\neq z) z(y̸=z),设其修改时间为 t x t_x tx,存在以下关系:

    • y y y需要修改,则 t y > t x t_y>t_x ty>tx
    • z z z需要修改,则 t z < t x t_z<t_x tz<tx

    拓扑排序判断是否有解。

  • A → B A\to B AB不存在不动点。 O ( n 3 ) O(n^3) O(n3)枚举第一次选择的叶节点和改变后指向的点,在第一次操作后强制其为不动点拓扑排序判断。

两种情况都尝试一下,复杂度 O ( n 3 T ) O(n^3T) O(n3T)

你可能感兴趣的:(妙,二分图匹配,贪心,atcoder)