https://atcoder.jp/contests/abc329

G -  Delivery on Tree

n点,二叉树,根1

m 球, 每个球有 初始点 和 目标点

1个篮子 初始空,位置在1, 最大容量k

每次可以 移动篮子, 装入在起始位置的球,放出在目标位置的球,不能超过最大容量

最终篮子还要回到点1

问 有多少种路径方案方案,经过每条边恰好2次 mod 998244353,且所有球被移动到了目标位置

n 1e4

m 2e5

k 1e3

3s

1024mb

我的思路

2个关键性质:二叉树,所有边恰好走2次

对于一个二叉树的一个有分叉节点来说

如果有左侧向右侧的移动,那么 左侧先于右侧访问

如果有右侧向左侧的移动,那么 右侧先于左侧访问

如果同时有则方案为0

由上 我们可以知道一些 节点的左右的访问先后顺序

那么剩下的就是 点到祖先节点的移动,和祖先到后代的移动

对于 跨 lca的移动来说 可以拆分成 u->lca(u,v) 和 lca(u,v)->v

O(m log n) 可以完成


问题变成n点,2m条 下向上和上向下的 移动限制, 和部分节点有先后顺序的限制的合法方案数

一个问题是移动能否拆成单位距离1的移动?

注意到从上向下的时候 当遇到起始时,且边向内有目标点时,一定要拿起,而遇到放下时,优先放下更优,

而从下向上时, 离开的时候 拿起更优,而到终点时一定要放下

所以 把所有路径可以拆分成 很多单位距离为1的路径,并且同样的贪心规则向下的一定拿起,向上的第二次遇到拿起,能放下就放下,并且在限制了 左右先后以后 对于跨lca的需要注意的是,拿起时 是进入lca(u,v)->v方向的对应边的时候,而不是首次,而对于分叉的其实一样

所以稍微改一下,是进入边 和 离开边产生增加 和减少,不再放在点上

通过树上前缀和 可以 O(m+n)完成


所以变成n个点 有向但双向边,每个边有一个 进入增加,和离开减少,保持 <=k 的方案数

k 1e3 不算大

想法是dp[u][l/r] = map<inc,cnt> 是走这一侧合法的 增量集合? 能做吗?


AC倒是AC了就是写得有点久

閱讀全文 »

https://ac.nowcoder.com/acm/contest/69791

F - 小辰刚学 gcd

https://ac.nowcoder.com/acm/contest/69791/F

长度n数组a

m个询问, 每次求query(l,r) = 集合{gcd(a[i..r]),i=l..r}的大小

范围

n 6e5

$a_i \in [1,2^{31}]$

1s

256MB

我的思路

显然 集合中的数 一定是 a[r] 的 因子,且两两互为倍数

所以 最多32个

然后我糊了一个st表+幂次查询,应该是 $O((n+m)\log(a_i)\log(n))$

TLE了

https://ac.nowcoder.com/acm/contest/view-submission?submissionId=65524654

閱讀全文 »

https://codeforces.com/contest/1893

n个 有色块, 第i个颜色$a_i$

安排它们到m个书架, 第i个书架 能放s_i个, $\sum s_{1\dots m} = n$

colorfulness(一个书架) = 该书架上同色块的最近距离(index差), 如果全部不同色则等于s_i

对于书架i有colorfulness下限di需求

提供摆放方案, 或者判断无法满足需求

m,n 2e5

3s

512mb

我的思路

下限的意思就是越大越好

确定了一个书架上放哪些块,那么????

好像一个书架上都没有什么想法

那就按照下限做, 先放个数最多的,然后它就按照下限要求放间隔

问题是 8容量,但是间隔下限要求3, wxyzwxyz是方案

但按照 下限要求 wxywxyzz 会卡住

閱讀全文 »

https://atcoder.jp/contests/abc327

G -  Many Good Tuple Problems

(S,T) = 一对 长度m值域[1,n]的序列

若 存在长度n的 0/1 串x,使得 所有i=1..m, x[s[i]] != x[t[i]], 那么称 s,t为一对好的

在所有的$n^{2m}$个方案中, 问好的序列有多少个 mod 998244353

n 30

m 1e9

2s

1024mb

我的思路

D 题是判断是否是好的序列

其实s[i],t[i] 就是指定了一对x中0/1相反的位置,而如果多个si,ti连接了了一系列坐标,如果有合法方案那么这一系列被连着的坐标 全部做0/1 翻转也合法,而和这个连通关系分离的位置,不会影响

所以s[i],t[i] 唯一需要满足的就是 任何环都是偶数长度


然后n比较小,但不是很小 不够bitmask,一半够bitmask

m很大,O(m)都过大

所以 范围推方向大概 要在 n上建立维度,而m直接用到计算里

f(sz) = sz个x连通的内部合法的方案数

g(sz) = sz个合法的方案数

$g(sz) = \sum_{t=1\cdots sz} \binom{sz-1}{t-1} f(t)g(sz-t)$, 这样sz中最小的点一定在f中,f中保证一块

这样的问题是 这里缺失了m的性质

而且f似乎不太好算


改一下 f(vertex,edge)= vertex个点edge条边(可重边) 连通的方案数

g(vertex,edge)= vertex个点edge条边(可重边)的方案数

$\displaystyle g(i,j) = \sum_{t=1\cdots i,k=0\cdots j} \binom{i-1}{t-1} f(t,k)g(i-t,j-k)$

答案是$g(n,m)$

这样的问题是 状态 和转移代价都太大


改一下 f(vertex,edge)= vertex个有序点edge条无向边(无重边) 连通的方案数

g(vertex,edge)= vertex个有序点edge条无向边(无重边)的方案数

$\displaystyle g(i,j) = \sum_{t=1\cdots i,k=0\cdots j} \binom{i-1}{t-1} f(t,k)g(i-t,j-k)$

答案是$\displaystyle \sum_{c=0\cdots\frac{n(n-1)}{2}} g(n,c) p(m,c)2^m$

其中$p(m,c)$表示m个有序号球染色c种,每个颜色至少一个球的方案数,这里相当于选边,而$2^m$相当于边的正向和逆向

这样的好处是,当有了无重边的限制以后,$\mathrm{edge}\le \frac{\mathrm{vertex}(\mathrm{vertex}-1)}{2}$


两个问题 f怎么算?

f的想法是 如果连通,那么钦定最小点为颜色0,和其它点的颜色0/1

可选的边有 count(0) * count(1)

再减去不连通的?

$h(i,j,c)=$i个有序0,j个有序1,c条边,所有连通的方案数

$l(i,j,c)=$i个有序0,j个有序1,c条边 的任意方案数 = $\binom{ij}{c}$

$h(i,j,c) = l(i,j,c) - \sum \binom{i-1}{i_0-1}\binom{j}{j_0} h(i_0,j_0,c_0)l(i-1-i_0,j-j_0,c-c_0)$

其中$1+i_0+j_0 < i+j$

$f(i,j) = \sum_{t=0\cdots i-1} \binom{i-1}{t} h(1+t,i-(1+t),j)$


p怎么算?

m太大

p(m,c(n^2))

$p(m,c) = \sum_{t}\binom{m}{t}p(m-t,c-1)$

$\frac{p(m,c)}{m!} = \sum_{t}\frac{1}{t!}\frac{p(m-t,c-1)}{(m-t)!}$

令 $q(m,c) = \frac{p(m,c)}{m!}$

$q_{c} = q_{c-1} (e^x-1)$

$q_{c} = (e^x-1)^c$

$p(m,c) = m! x^m^c$

后面的$e^x-1$ 展开成幂级数,m太大不好算,不如二项式展开,直接上手

$\displaystyle p(m,c) = m! [x^m](\sum_{i=0}^c \binom{c}{i}(e^x)^i(-1)^{c-i})$

$\displaystyle p(m,c) = m! (\sum_{i=0}^c \binom{c}{i}\frac{i^m}{m!}(-1)^{c-i})$

$\displaystyle p(m,c) = (\sum_{i=0}^c \binom{c}{i}i^m(-1)^{c-i})$


h状态有O(n^4) ?, 如何快速算出, 还是打表?

  • 没加-fsanitize=integer 1.2s
  • 加了-fsanitize=integer 9s

f(i(n),j(n2)) 可以$O(n^4)$ 算出

g(i(n),j(n2)) 似乎需要O(n^5)

m个给定的, 直接for c(n^2)就好了 O(n^4)能算出


综上

i有序0,j有序1,c边 无重连:

$l(i,j,c)=\binom{ij}{c}$

i有序0,j有序1,c边 无重连 所有连通:

$\displaystyle h(i,j,c) = l(i,j,c) - \sum_{i_0=1}^{i}\sum_{j_0=0,i_0+j_0 < i+j}^{j}\sum_{c_0=0}^c \binom{i-1}{i_0-1}\binom{j}{j_0} h(i_0,j_0,c_0)l(i-i_0,j-j_0,c-c_0)$

i个有序点,j边,合法 所有连通:

$\displaystyle f(i,j) = \sum_{t=1}^i \binom{i-1}{t-1} h(t,i-t,j)$

i个有序点,j边,合法:

$\displaystyle g(i,j) = \sum_{t=1}^{i}\sum_{k=0}^{j} \binom{i-1}{t-1} f(t,k)g(i-t,j-k)$

m个有序点 上色c种,每个颜色至少一个点

$\displaystyle p(m,c) = (\sum_{i=0}^c \binom{c}{i}i^m(-1)^{c-i})$

最终答案为

$\displaystyle 2^m \sum_{c=0}^{\frac{n(n-1)}{2}} g(n,c) p(m,c)$


然而 pretest 对了2个点,错了两个点,emmmmmmmmmmmm

提交了一下 还ac x21, wa x21

我错哪里了????????????????????????????????????????????????

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#include <bits/stdc++.h>
#include <atcoder/modint>
const int MOD=998244353;
using mint = atcoder::static_modint<MOD>;
using namespace std;
typedef long long ll;
#define rep(i,a,n) for (ll i=a;i<(ll)(n);i++)
#define per(i,a,n) for (ll i=n;i-->(ll)(a);)
ll read(){ll r;scanf("%lld",&r);return r;}
const int N=30;
const int MXEDGE=225; // 最大边数
mint h[N+1][N+1][MXEDGE+1]; // h[有序0个数][有序1个数][无重边数]=全连通方案数
mint f[N+1][MXEDGE+1]; // f[有序点数][边数] = 合法全通方案数
mint g[N+1][MXEDGE+1]; // g[有序点数][边数] = 合法方案数
mint p[N+1]; // p[c] = m个有序点 上色c种,每种颜色至少一个点的方案数
mint fac[MXEDGE+10]={1};
mint ifac[MXEDGE+10]={1};
mint binom(int n,int m){return (m>n or m<0)?0:(fac[n]*ifac[m]*ifac[n-m]);}
int main(){
rep(i,1,MXEDGE+1) fac[i]=fac[i-1]*i;
ifac[MXEDGE]=fac[MXEDGE].inv();
per(i,0,MXEDGE) ifac[i]=ifac[i+1]*(i+1);
int n=read();
int m=read();
rep(i,1,N+1) rep(j,0,N+1-i) rep(c,0,i*j+1){
h[i][j][c] = binom(i*j,c); // 不重复任意连c条
rep(i0,1,i+1) rep(j0,0,j+1) if(i0+j0 != i+j) rep(c0,0,min(i0*j0,c)+1) { // 与最小i相连的连通块
h[i][j][c] -= h[i0][j0][c0]*binom(i-1,i0-1)*binom(j,j0)*binom((i-i0)*(j-j0),c-c0);
}
}
// 没加-fsanitize 1.2s
// 加了-fsanitize 9s
rep(i,1,N+1) rep(j,0,MXEDGE+1) rep(t,1,i+1) f[i][j] += binom(i-1,t-1) * h[t][i-t][j];
g[0][0] = 1;
rep(i,1,N+1) rep(j,0,MXEDGE+1) rep(t,1,i+1) rep(k,0,j+1) g[i][j] += binom(i-1,t-1)*f[t][k]*g[i-t][j-k];
vector<mint> impwr(MXEDGE+1);
rep(i,0,MXEDGE+1) impwr[i] = mint(i).pow(m);
rep(c,1,MXEDGE+1) rep(i,0,c+1) p[c] += binom(c,i) * impwr[i] * ((c-i)%2==0?1:-1);
mint ans =0;
rep(c,0,MXEDGE+1) ans += g[n][c]*p[c];
printf("%d\n",(ans*mint(2).pow(m)).val());
return 0;
}
閱讀全文 »

https://codeforces.com/contest/1889

C2

长n数组上有m个区间[li,ri]

问删除k 个区间后 未被任何区间覆盖的 位置个数最多能有多少

$n \le 2\cdot 10^5$

$m \le 2\cdot 10^5$

$k \le 10$

4s

1024mb

我的思路

题目C1中,k=2, 这样的话

被覆盖0次,则一定贡献

被覆盖1次,则对应区间删除则贡献

被覆盖2次,则对应两个区间删除则贡献

被覆盖> 3次,则一定不贡献

对于被覆盖恰好两次的部分,考虑到如果 区间A和B相交, 则可以看成变为 A并B的新区间 和 A交B的消耗区间, 这样可以继续相互重叠的区间个数 -1, 所以恰好两次的部分的种类数 $\le m$

可以 线段树,for一遍之类的 完成对应的统计,

统计,单色=>个数,色对=>个数

ans = max(max两个单色,色对AB+单色A+单色B)


这样的思路下,C2感觉就很复杂了, 像是颜色集合子集的个数和

閱讀全文 »
0%