1. 程式人生 > >牛客國慶集訓派對Day4 I-連通塊計數(思維,組合數學)

牛客國慶集訓派對Day4 I-連通塊計數(思維,組合數學)

時間限制:C/C++ 1秒,其他語言2秒 空間限制:C/C++ 1048576K,其他語言2097152K 64bit IO Format: %lld

題目描述

小 A 有一棵長的很奇怪的樹,他由 n 條鏈和 1 個點作為根構成,第 i 條鏈有 ai 個點,每一條鏈的一端都與根結點相連。 現在小 A 想知道,這棵長得奇怪的樹有多少非空的連通子樹,你只需要輸出答案對 998244353 取模的值即可

輸入描述:

第一行一個正整數 n
第二行 n 個正整數 a1…an

輸出描述:

輸出答案對 998244353 取模後的值

示例1

輸入

2
1 1

輸出

6

備註:

1≤ n≤ 10^5
1≤ ai≤ 10^7

思路

連通塊分成兩種:連通子樹的點在同一條鏈上和在多條鏈上;

  • 連通子樹的點在一條鏈上:算上根節點,每條鏈上一共有a[i]+1個點,每條鏈上有C^{2}_{a_{i}+1}個連通子樹,所以該情況的連通子樹共有\sum C^{2}_{a_{i}+1}
  • 連通子樹的點在多條鏈上:每條鏈上有選擇0,1,2,......a[i]這a[i]+1種選法,所以該情況一共有\prod \left( a\left[ i\right] +1\right)個連通子樹

然後把上述兩種情況的連通子樹數量相加即可

AC程式碼

/*
* @Author: WZY
* @Date:   2018-10-09 16:36:48
* @Last Modified by:   WZY
* @Last Modified time: 2018-10-09 17:28:52
*/
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <math.h>
#include <limits.h>
#include <map>
#include <stack>
#include <queue>
#include <vector>
#include <set>
#include <string>
#include <time.h>
#define ll long long
#define ull unsigned long long
#define ms(a) memset(a,0,sizeof(a))
#define pi acos(-1.0)
#define INF 0x7f7f7f7f
#define lson o<<1
#define rson o<<1|1
#define debug(...) cerr<<"["<<#__VA_ARGS__":"<<(__VA_ARGS__)<<"]"<<"\n"
const double E=exp(1);
const int maxn=1e6+10;
const int mod=998244353;
using namespace std;
ll a[maxn];
int main(int argc, char const *argv[])
{
	ios::sync_with_stdio(false);
	#ifndef ONLINE_JUDGE
	    freopen("in.txt", "r", stdin);
	    freopen("out.txt", "w", stdout);
	    double _begin_time = clock();
	#endif
	ll n;
	cin>>n;
	ll res=0;
	for(int i=0;i<n;i++)
	{
		cin>>a[i];
		res=res+(a[i]+1)*a[i]/2%mod;
	}
	ll ans=1;
	for(int i=0;i<n;i++)
		ans=ans*(a[i]+1)%mod;
	cout<<(ans+res)%mod<<endl;
	#ifndef ONLINE_JUDGE
	    long _end_time = clock();
	    printf("time = %lf ms.", _end_time - _begin_time);
	#endif
	return 0;
}