結果

問題 No.1075 木の上の山
ユーザー QCFiumQCFium
提出日時 2020-06-05 21:42:39
言語 C++14
(gcc 13.2.0 + boost 1.83.0)
結果
AC  
実行時間 65 ms / 2,000 ms
コード長 4,073 bytes
コンパイル時間 1,907 ms
コンパイル使用メモリ 181,468 KB
実行使用メモリ 23,200 KB
最終ジャッジ日時 2023-08-22 14:47:44
合計ジャッジ時間 4,675 ms
ジャッジサーバーID
(参考情報)
judge11 / judge13
このコードへのチャレンジ(β)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 2 ms
4,380 KB
testcase_01 AC 2 ms
4,380 KB
testcase_02 AC 2 ms
4,380 KB
testcase_03 AC 1 ms
4,380 KB
testcase_04 AC 1 ms
4,380 KB
testcase_05 AC 1 ms
4,376 KB
testcase_06 AC 2 ms
4,380 KB
testcase_07 AC 2 ms
4,376 KB
testcase_08 AC 2 ms
4,380 KB
testcase_09 AC 2 ms
4,376 KB
testcase_10 AC 3 ms
4,376 KB
testcase_11 AC 2 ms
4,376 KB
testcase_12 AC 2 ms
4,376 KB
testcase_13 AC 3 ms
4,376 KB
testcase_14 AC 3 ms
4,380 KB
testcase_15 AC 3 ms
4,380 KB
testcase_16 AC 3 ms
4,376 KB
testcase_17 AC 51 ms
23,200 KB
testcase_18 AC 64 ms
15,072 KB
testcase_19 AC 49 ms
20,252 KB
testcase_20 AC 65 ms
15,100 KB
testcase_21 AC 49 ms
8,436 KB
testcase_22 AC 48 ms
8,344 KB
testcase_23 AC 49 ms
8,868 KB
testcase_24 AC 48 ms
8,824 KB
testcase_25 AC 48 ms
8,360 KB
testcase_26 AC 62 ms
15,328 KB
testcase_27 AC 56 ms
11,480 KB
testcase_28 AC 49 ms
13,552 KB
testcase_29 AC 57 ms
12,724 KB
testcase_30 AC 63 ms
15,080 KB
testcase_31 AC 56 ms
16,436 KB
権限があれば一括ダウンロードができます

ソースコード

diff #

#include <bits/stdc++.h>

int ri() {
	int n;
	scanf("%d", &n);
	return n;
}
#define MOD 1000000007


template<int mod>
struct ModInt{
	int x;
	ModInt():x(0){}
	ModInt(long long y):x(y>=0?y%mod:(mod-(-y)%mod)%mod){}
	ModInt &operator+=(const ModInt &p){
		if((x+=p.x)>=mod)x-=mod;
		return *this;
	}
	ModInt &operator-=(const ModInt &p){
		if((x+=mod-p.x)>=mod)x-=mod;
		return *this;
	}
	ModInt &operator*=(const ModInt &p){
		x=(int)(1LL*x*p.x%mod);
		return *this;
	}
	ModInt &operator/=(const ModInt &p){
		*this*=p.inverse();
		return *this;
	}
	ModInt &operator^=(long long p){
		ModInt res = 1;
		for (; p; p >>= 1) {
			if (p & 1) res *= *this;
			*this *= *this;
		}
		return *this = res;
	}
	ModInt operator-()const{return ModInt(-x);}
	ModInt operator+(const ModInt &p)const{return ModInt(*this)+=p;}
	ModInt operator-(const ModInt &p)const{return ModInt(*this)-=p;}
	ModInt operator*(const ModInt &p)const{return ModInt(*this)*=p;}
	ModInt operator/(const ModInt &p)const{return ModInt(*this)/=p;}
	ModInt operator^(long long p)const{return ModInt(*this)^=p;}
	bool operator==(const ModInt &p)const{return x==p.x;}
	bool operator!=(const ModInt &p)const{return x!=p.x;}
	explicit operator int() const { return x; }						   // added by QCFium
	ModInt operator=(const int p) {x = p; return ModInt(*this);} // added by QCFium
	ModInt inverse()const{
		int a=x,b=mod,u=1,v=0,t;
		while(b>0){
			t=a/b;
			a-=t*b;
			std::swap(a,b);
			u-=t*v;
			std::swap(u,v);
		}
		return ModInt(u);
	}
	friend std::ostream &operator<<(std::ostream &os,const ModInt<mod> &p){
		return os<<p.x;
	}
	friend std::istream &operator>>(std::istream &is,ModInt<mod> &a){
		long long x;
		is>>x;
		a=ModInt<mod>(x);
		return (is);
	}
};
typedef ModInt<MOD> mint;

struct MComb {
	std::vector<mint> fact;
	std::vector<mint> inv;
	MComb (int n) { // O(n + log(mod))
		fact = std::vector<mint>(n + 1, 1);
		for (int i = 1; i <= n; i++) fact[i] = fact[i - 1] * mint(i);
		inv.resize(n + 1);
		inv[n] = fact[n] ^ (MOD - 2);
		for (int i = n; i--; ) inv[i] = inv[i + 1] * mint(i + 1);
	}
	mint ncr(int n, int r) {
		return fact[n] * inv[r] * inv[n - r];
	}
	mint npr(int n, int r) {
		return fact[n] * inv[n - r];
	}
	mint nhr(int n, int r) {
		assert(n + r - 1 < (int) fact.size());
		return ncr(n + r - 1, r);
	}
};


std::vector<std::vector<int> > hen;
int k;

std::vector<mint> merge(const std::vector<mint> &l, const std::vector<mint> &r) {
	int n = l.size();
	std::vector<mint> res(n);
	mint suml = 0, sumr = 0;
	for (int i = 0; i < k; i++) {
		suml += l[i];
		sumr += r[i];
		res[i] += suml * r[i];
		res[i] += sumr * l[i];
		res[i] -= l[i] * r[i];
	}
	return res;
}

mint res;
std::vector<std::vector<mint> > subtree;
void dfs0(int i, int prev) {
	if (prev != -1) hen[i].erase(std::find(hen[i].begin(), hen[i].end(), prev));
	subtree[i].resize(k);
	subtree[i][0] = 1;
	for (auto j : hen[i]) {
		dfs0(j, i);
		subtree[i] = merge(subtree[i], subtree[j]);
	}
	for (int j = 0; j + 1 < k; j++) subtree[i][j + 1] += subtree[i][j];
}
void dfs1(int i, int prev, const std::vector<mint> &par_dp) {
	int m = hen[i].size();
	mint sumed = 0;
	for (int j = 0; j < k; j++) {
		res += subtree[i][j] * (prev == -1 ? 1 : sumed);
		if (prev != -1) sumed += par_dp[j];
	}
	if (m) {
		std::vector<std::vector<mint> > left(m);
		std::vector<std::vector<mint> > right(m);
		std::vector<mint> tmp(k);
		tmp[0] = 1;
		left.front() = right.back() = tmp;
		for (int j = 0; j + 1 < m; j++) left[j + 1] = merge(left[j], subtree[hen[i][j]]);
		for (int j = m; --j; ) right[j - 1] = merge(right[j], subtree[hen[i][j]]);
		for (int j = 0; j < m; j++) {
			auto tmp = merge(merge(left[j], right[j]), par_dp);
			for (int l = 0; l + 1 < k; l++) tmp[l + 1] += tmp[l];
			dfs1(hen[i][j], i, tmp);
		}
	}
}

int main() {
	int n = ri();
	k = ri();
	hen.resize(n);
	for (int i = 1; i < n; i++) {
		int a = ri() - 1;
		int b = ri() - 1;
		hen[a].push_back(b);
		hen[b].push_back(a);
	}
	subtree.resize(n);
	dfs0(0, -1);
	std::vector<mint> tmp(k);
	tmp[0] = 1;
	dfs1(0, -1, tmp);
	std::cout << res << std::endl;
	return 0;
}
 
0