2023年湖南acm省賽 I題(2019)

2021-09-27 13:38:53 字數 1527 閱讀 2439

有一顆 n 個點的帶權樹,點的編號是 1, 2, …, n. 樹有 (n - 1) 條邊,求樹上兩點之間的距離是2019的倍數的點對有多少?

點對距離計數:點分治

點分治關鍵是對cal函式進行修改,其他的基本不用改。如何靈活運用cal函式,主要還是要理解幾個變數的含義。根據點分治的過程,是不斷找重心,然後<1>求出每個點到重心的距離,同時用乙個陣列temp記錄這些距離,再對各個子樹進行分治,過程一樣。而cal函式就是在計算完<1>後,對temp進行操作,怎麼改,看具體的題目。這裡有個點需要注意,就是<1>操作會把所有點到重心的距離也算進去(加入傳入重心,就會有乙個零),所以temp必然會包含乙個len(len是calc的引數)。總的來說calc就是計算完其他點到某一點的距離後,對這些點的距離進行處理的中間過程。

cal改法

int cc[2019];

inline int calc(int x,int len)

2019倍數,很容易想到取餘處理,設b為重心,a->b+b->c=2019,就說明a->c是2019的倍數。

這樣其實還有乙個問題,就是重複計算。下面通過**,解釋如何處理。

a為重心,每一點到重心距離已經得到,但是通過cal函式會把b->a和c->a的距離也加上,所以需要把這種可能排除,我們最終的結果是,記錄每次分治不同子樹之間的距離,而同一子樹之間的點對需要排除。如何排除,ans-=cal(h,c)即可,對h的子節點到h的距離點對加上c,這些答案需要排除。

#includeusing namespace std;

#define ios ios::sync_with_stdio(false)

const int n = 20020, inf = 0x7f7f7f7f;

int n,head[n*2],num,tot,ans;//tot記錄當前子樹點數

int dis[n],flag[n],temp[n];

//dis記錄子樹每一點到根節點的距離,flag用於刪除根節點,temp總匯到根節點的距離

int size[n],max[n],root;

struct edge

g[n*2];

void add(int from,int to,int len)

inline void input(void)

}inline void dp(int fa,int cur)//求樹的重心

max[cur] = max( max[cur], tot - size[cur] );

if ( max[root] > max[cur] ) root = cur;

}inline void dfs(int fa,int cur)

}int cc[2019];

inline int calc(int x,int len)

inline void divide(int x)

return 0;

}

2019湖南「強智杯」省賽A題

bobo 寫了乙個 n 行 m 列的矩陣 ai,j.首先,他把所有元素 ai,j 1 i n,1 j m 設為 0.然後,他選了 4 個整數 x1,x2,y1,y2 滿足 1 x1 x2 n,1 y1 y2 m,並把滿足 x1 i x2,y1 j y2 的元素 ai,j 設為 1.給出 n 行 m ...

湖南省2017省賽A題

題目大意,給你n個數,要求你給出任意乙個排列,要求乙個數與左右的數的差值的絕對值大小大於d。直接遞推,設第乙個數為a,則第二個數顯然最大為n,那麼可以推出a n d 1,第三個數為a 1,第四個數為a d。以此可遞推出第i個數大小為,分奇偶性,i為奇數時,其為a i 1 2,偶數時,a d i 4 ...

2023年省賽I題 Thrall s Dream

2013年省賽i題 判斷單向聯通,用bfs 剪枝 從小到大跑,如果遇到之前跑過的點 也就是編號小於當前點的點 就o n 傳遞關係。bfs1 include2 include3 include4 include5 include6 include7 include 8 include9 include...