牛客國慶集訓派對Day4——I 連通塊計數(思維)
阿新 • • 發佈:2018-12-13
題目大意:
小 A 有一棵長的很奇怪的樹,他由 n 條鏈和 1 個點作為根構成,第 i 條鏈有 ai 個點,每一條鏈的一端都與根結點相連。 現在小 A 想知道,這棵長得奇怪的樹有多少非空的連通子樹,你只需要輸出答案對 998244353 取模的值即可
題解:
注意題目說的是每條鏈的一端都與根節點相連,只是這條鏈的最末端,端點與根節點相連,那些在這條鏈上卻非末端端點的點不與根節點相連
就像這個樣子
這樣的話,連通子樹的個數要分兩種情況
1.包含根節點
對於每一條鏈,鏈的末端與根節點相連,構成了一個迴路,每一條鏈有a[i]個點,那麼就有在這條鏈選0個、選1個、選2個...選a[i]個,共a[i]+1種情況,
要構成連通子樹,必須得是相連的,就是根-1,根-1-2,根-1-2-3......這樣的情況,不可能直接選中途的1-2這樣
2.不包含根節點
對於每一條鏈,有a[i]個節點,那麼這條鏈能形成的子樹個數是 ,這是通過挨個數找出的規律,
例如本圖最左邊的鏈,分別給點標號為1,2,3,4
子樹的個數為
①4個節點分別是1個
②1-2,1-2-3,1-2-3-4
③2-3,2-3-4,
④3-4
共10個
因為沒跟根節點連線,就不能乘了,要加起來,所以
踩的坑:
首先,這個題有除以2,但是不用求逆元,當能夠保證整除的情況下不需要求逆元(a[i]*(a[i]+1)也一定能夠整除2),當是分數的情況下才需要求逆元(又漲姿勢了),但是求了也沒錯。
其次,在算的過程中,ans是long long 型別的,而a[i]是int型的,算的過程有相乘,數大了就會爆int的,沒有轉換型別,導致WA了一發。。。。
#include<bits/stdc++.h> using namespace std; #define mod 998244353 typedef long long ll; int a[100010]; int main() { // freopen("input.txt","r",stdin); int n; scanf("%d",&n); for(int i=1; i<=n; ++i) scanf("%d",&a[i]); ll ans1=1; for(int i=1; i<=n; ++i) { ans1*=a[i]+1; ans1%=mod; } ll ans2=0; for(int i=1; i<=n; ++i) { ans2+=(ll)(a[i])*(a[i]+1)/2%mod; ans2%=mod; } printf("%lld\n",(ans1+ans2)%mod); return 0; }