hdu-6986
VJ链接
题意:
给定一棵树,每棵树有一个点权
c
i
∈
[
1
,
n
]
c_i\in[1,n]
ci∈[1,n]
定义
p
(
u
,
v
)
p(u,v)
p(u,v) 表示
u
u
u–>
v
v
v 这条路径上点权的种类数
设
a
i
j
a_{ij}
aij 表示
p
(
i
,
j
)
p(i,j)
p(i,j) 这条路径上的种类数
定义
f
(
i
,
x
)
=
∑
j
=
1
n
a
i
,
j
x
j
−
1
f(i,x)=\sum_{j=1}^n a_{i,j}x^{j-1}
f(i,x)=j=1∑nai,jxj−1
每个测试点输出
n
n
n 行,每行输出两个数,
f
(
i
,
19560929
)
%
(
1
0
9
+
7
)
f(i,19560929)\% (10^9+7)
f(i,19560929)%(109+7) 和
f
(
i
,
19560929
)
%
(
1
0
9
+
9
)
f(i,19560929) \% (10^9+9)
f(i,19560929)%(109+9)
思路:
加减一法
code:
#include<bits/stdc++.h>
#define endl '\n'
#define ll long long
#define ull unsigned long long
#define ld long double
#define all(x) x.begin(), x.end()
#define mem(x, d) memset(x, d, sizeof(x))
#define eps 1e-6
using namespace std;
const int maxn = 2e3 + 9;
const int mod1 = 1e9 + 7;
const int mod2 = 1e9 + 9;
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
ll n, m;
const int b = 19560929;
int base1[maxn], base2[maxn], c[maxn], p[maxn], cnt[maxn];
vector <int> e[maxn];
int ans;
void init(){
base1[0] = base2[0] = 1;
for(int i = 1; i <= maxn - 9; ++i){
base1[i] = 1ll * base1[i-1] * b % mod1;
base2[i] = 1ll * base2[i-1] * b % mod2;
}
}
inline void add(int x)
{
if (!cnt[x]) ++ans;
++cnt[x];
}
inline void del(int x)
{
if (cnt[x] == 1) --ans;
--cnt[x];
}
void dfs(int x, int fa){
add(c[x]);
p[x] = ans;
for(auto to : e[x]) if(to != fa) dfs(to, x);
del(c[x]);
}
void work()
{
cin >> n;
for(int i = 1; i <= n; ++i) e[i].clear();
ans = 0;
for(int i = 1; i < n; ++i){
int x, y;cin >> x >> y;
e[x].push_back(y);
e[y].push_back(x);
}
for(int i = 1; i <= n; ++i) cin >> c[i];
for(int i = 1; i <= n; ++i){
dfs(i, -1);
ll ans1 = 0, ans2 = 0;
for(int j = 1; j <= n; ++j)
{
(ans1 += 1ll * base1[j-1] * p[j]) %= mod1;
(ans2 += 1ll * base2[j-1] * p[j]) %= mod2;
}
cout << ans1 << " " << ans2 << endl;
}
}
int main()
{
ios::sync_with_stdio(0);
init();
// int TT;cin>>TT;while(TT--)
work();
return 0;
}