[题解向] 正睿Round409

Posted pks-t

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[题解向] 正睿Round409相关的知识,希望对你有一定的参考价值。

( m Link)

然而泥萌没有权限是看不了题目的233.

( m T1)

大概就是个map,脑残出题人认为(x,x)不属于有序二元组,我可qtmd。于是只拿了( m 60pts)

int main(){
    ios_base :: sync_with_stdio(false) ;
    cin.tie(0), cout.tie(0) ; cin >> N >> P ; int i ; 
    for (i = 1 ; i <= N ; ++ i) cin >> base[i], base[i] %= P ; 
    for (i = 1 ; i <= N ; ++ i) if (base[i]) M[expow(4 * base[i] % P, P - 2)] ++ ;
    for (i = 1 ; i <= N ; ++ i){
        int now = 1ll * base[i] * base[i] % P ; 
        ans += M[now] ; if (4ll * now % P * base[i] % P == 1) -- ans ;  
    }
    cout << ans << endl ; return 0 ;    
} 

( m T2)

先说自己的做法。

发现其实就是在凑一个式子:

[frac{sum a_ik_i}{Msum k_i}=frac{N}{M}]

然后稍微变个形:

[sum a_ik_i=Ncdot sum k_i]

于是发现只要暴力背包就完了,最后判断一下(f_{k,N})是不是(=k)就做完了。

int main(){
    cin >> K >> N >> M ; int i, j ; dp[0] = 0 ; 
    for (i = 1 ; i <= K ; ++ i) cin >> base[i] ; 
    for (i = 1 ; i <= N * N ; ++ i) dp[i] = Inf ; 
    for (i = 1 ; i <= K ; ++ i)
        for (j = base[i] ; j <= N * N ; ++ j)
            dp[j] = min(dp[j - base[i]] + 1, dp[j]) ; 
    for (i = 1 ; i <= N ; ++ i) if (dp[i * N] == i) return cout << i, 0 ;
    return -1 ;  
}

于是获得了( m 70pts)……但是用头想一想,发现并不对。因为可能(f_{k,N})这个状态的( m cost)可能是5,但是背包转移的时候只能记录最优状态,于是假设会记录4,那这个状态就挂掉了……对每个状态都开了个std :: set发现T掉了……

正解是BFS。

考虑把式子转化一下,就变成了

[sum k_i(a_i-N)=0]

大概就是考虑用已经凑出的和当做状态,那么实际上是在找一个环。于是每次转移的时候枚举放哪个新物品(新物品权值为(a_i-N))就完了。

#define MAX 50000
    cin >> K >> N >> M ; q.push(MAX) ; vis[MAX] = 1 ; int i ;
    for (i = 1 ; i <= K ; ++ i) cin >> base[i], base[i] -= N ; 
    while (!q.empty()){
        int now = q.front() ; q.pop() ; 
        if (now > M + MAX) continue ;
        for (i = 1 ; i <= K ; ++ i){
            if (now + base[i] == MAX){
                cout << ans[now] + 1 << endl ; 
                return 0 ; 
            }
            else if (!vis[now + base[i]]) 
                vis[now + base[i]] = 1, ans[now + base[i]] = ans[now] + 1, q.push(now + base[i]) ;
        }
    }
    cout << -1 << endl ; 

正 解 暴 力, 菜 鸡 退 役。

( m T3)

sb题,每个连通块都产生( m 1)的贡献当且仅当没有任何一个连通块是树。

于是就变成了找树的问题……忘记前驱思考了nm老久,趁早退役算了= =

void dfs(int now, int pre){
    vis[now] = 1 ;
    for (int k = head[now] ; k ; k = E[k].next){
        if (to(k) == pre) continue ; 
        if (to(k) == now) continue ; 
        if (!vis[to(k)]) dfs(to(k), now) ; else ++ o ; 
    } 
}
int main(){
    cin >> N ; int i ; p = 1 ; 
    for (i = 1 ; i <= N ; ++ i) fa[i] = i ; 
    for (i = 1 ; i <= N ; ++ i) cin >> base[i], add(i, base[i]) ; 
    for (i = 1 ; i <= N ; ++ i) if (fa[i] == i) ++ ans ;// cout << ans << endl ; 
    for (i = 1 ; i <= N ; ++ i) if (!vis[i]) o = 0, dfs(i, 0), p = min(o, p) ; 
    if (p) cout << ans << endl ; else cout << ans - 1 << endl ; 

( m T4)

BZOJ4160.

不可做题233

题面:

给定一张无向图,求给这张图定向成( m DAG)之后最长路最短是多少。(nleq 16)

( m{Sol~1})

考虑直接(dp)(f_{s,u,v})表示考虑了点集(s),最长路端点是(u,v)的最小值。每次转移的时候枚举(u,v,w),从((u,v),(v,w))两个状态转移到((u,w))。复杂度(O(3^nn^3))

1h没调出来

( m Sol~2)

考虑证明一个二级定理:

定理 (1.1)

  • 一张无向图定向成的( m DAG),当其最长路最短时,其最长路为( m X-1),其中( m X)表示不连通集覆盖数。也就是对于一张有向图图( m {V,E}),定义一种划分(P),使得划分出的每个集合中所有点不连通。

考虑一种证明:

  • 首先一定有( m X-1geq maxL)。因为其上的每个点是连通的。
  • 其次我们考虑,如果每次删除全部出度为(0)点,放到一个集合里,那么一定合法,并且可以满足( m X=maxL+1)

但其实这东西也可以直接用( m dilworth)定理的对偶定理证出来:

定理 (2.1)( m dilworth)定理)

( m (X,≤))是一个有限偏序集,并令(m)是反链的最大的大小。则( m X)可以被划分成(m)个但不能再少的链。

对偶一下:

定理 (2.2):
( m (X,≤))是一个有限偏序集,并令(r)是其最大链的大小。则(X)可以被划分成(r)个但不能再少的反链。

然后”反链“连接的是”不可比的点“,也就是本题中”不连通的点“。

于是我们就可以快乐地状压了。

int *g, *f ;
int main(){
    cin >> N >> M ; 
    memset(f, 63, sizeof(f)) ; 
    int u, v, i, j ; T = (1 << N) - 1 ;
    for (i = 1 ; i <= M ; ++ i)
        cin >> u >> v, -- u, -- v, E[u] |= (1 << v), E[v] |= (1 << u) ;
    f[0] = 0, g[0] = 1 ; 
    for (i = 0 ; i <= N ; ++ i) Sz[1 << i] = i ; 
    for (i = 1 ; i <= T ; ++ i){
        j = (i & (-i)) ;
        if (!g[i ^ j]) continue ; 
        if (E[Sz[j]] & (i ^ j)) continue ; 
        g[i] = 1 ; 
    }
    for (i = 1 ; i <= T ; ++ i)
        for (j = i ; j ; j = (j - 1) & i)
            if (g[j]) f[i] = min(f[i], f[i ^ j] + 1) ; 
    cout << f[T] - 1 << endl ; return 0 ;
}

以上是关于[题解向] 正睿Round409的主要内容,如果未能解决你的问题,请参考以下文章

正睿2018暑假集训 比赛题选做

Codeforces Round #409 (Div. 2)

题解 2019正睿普及五连测T4——流浪地球

Codeforces Round 409 (Div. 2)

zr2019暑期高端峰会AB组十测

正睿2019暑假集训正睿892 蔡老板与宝藏