This submission is migrated from previous version of oj.uz, which used different machine for grading. This submission may have different result if resubmitted.
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
const int MAXN = 1e5;
const ll MOD = 1e9+7;
int N; ll D;
vector<int> adj[MAXN+10];
typedef vector<vector<ll>> Mat;
Mat operator * (const Mat &p, const Mat &q)
{
Mat ret=vector<vector<ll>>(p.size(), vector<ll>(q[0].size()));
assert(p[0].size()==q.size());
for(int i=0; i<p.size(); i++) for(int j=0; j<q[0].size(); j++)
{
for(int k=0; k<p[0].size(); k++)
{
ret[i][j]+=p[i][k]*q[k][j]%MOD;
ret[i][j]%=MOD;
}
}
return ret;
}
Mat mypow(Mat x, ll y)
{
if(y==0) return {{1, 0}, {0, 1}};
if(y%2) return mypow(x, y-1)*x;
Mat t=mypow(x, y/2);
return t*t;
}
ll ans;
ll a, b, c, d, p, q, x, y;
int dp[MAXN+10], dp2[MAXN+10], zero;
int cnt0[MAXN+10], cnt1[MAXN+10];
void dfs(int now, int bef)
{
for(int nxt : adj[now])
{
if(nxt==bef) continue;
dfs(nxt, now);
dp[now]+=!dp[nxt];
}
zero+=!dp[now];
dp2[now]=!dp[now];
for(int nxt : adj[now])
{
if(nxt==bef) continue;
if(dp[nxt]==0) cnt0[now]+=dp2[nxt];
else if(dp[nxt]==1) cnt1[now]+=dp2[nxt];
}
if(dp[now]==0) dp2[now]+=cnt1[now];
else if(dp[now]==1) dp2[now]+=cnt0[now];
}
void dfs2(int now, int bef)
{
//printf("%d : dp %d dp2 %d zero %d\n", now, dp[now], dp2[now], zero);
//for(int i=1; i<=N; i++) printf("%d : %d / ", i, dp2[i]); printf("\n");
if(dp[now]==0) c++;
else a++;
if(dp[now]==0) d+=N-zero;
else b+=N-zero;
if(dp[now]==0)
{
b+=dp2[now];
d+=zero-dp2[now];
}
else
{
d+=dp2[now];
b+=zero-dp2[now];
}
//printf("%lld %lld %lld %lld\n", a, b, c, d);
if(now==1) { x=a; y=b; }
for(int nxt : adj[now])
{
if(nxt==bef) continue;
int m1=dp2[now], m2=dp2[nxt];
int m3=cnt1[now], m4=cnt0[now], m5=cnt1[nxt], m6=cnt0[nxt];
zero-=!dp[now];
zero-=!dp[nxt];
dp[now]-=!dp[nxt];
if(dp[nxt]==0) cnt0[now]-=dp2[nxt];
else if(dp[nxt]==1) cnt1[now]-=dp2[nxt];
dp2[now]=!dp[now];
if(dp[now]==0) dp2[now]+=cnt1[now];
else if(dp[now]==1) dp2[now]+=cnt0[now];
dp[nxt]+=!dp[now];
if(dp[now]==0) cnt0[nxt]+=dp2[now];
else if(dp[now]==1) cnt1[nxt]+=dp2[now];
dp2[nxt]=!dp[nxt];
if(dp[nxt]==0) dp2[nxt]+=cnt1[nxt];
else if(dp[nxt]==1) dp2[nxt]+=cnt0[nxt];
zero+=!dp[nxt];
zero+=!dp[now];
dfs2(nxt, now);
zero-=!dp[now];
zero-=!dp[nxt];
dp[nxt]-=!dp[now];
dp[now]+=!dp[nxt];
zero+=!dp[nxt];
zero+=!dp[now];
dp2[now]=m1;
dp2[nxt]=m2;
cnt1[now]=m3; cnt0[now]=m4;
cnt1[nxt]=m5; cnt0[nxt]=m6;
}
}
int main()
{
scanf("%d%lld", &N, &D);
for(int i=1; i<N; i++)
{
int u, v;
scanf("%d%d", &u, &v);
adj[u].push_back(v);
adj[v].push_back(u);
}
dfs(1, 1);
dfs2(1, 1);
p=a; q=c;
a*=N; c*=N; x*=N;
a%=MOD; b%=MOD; c%=MOD; d%=MOD; x%=MOD; y%=MOD; p%=MOD; q%=MOD;
Mat M2={{a, b}, {c, d}};
Mat M1={{x, y}, {0, 0}};
Mat M3={{p}, {q}};
Mat MM=M1*mypow(M2, D-1)*M3;
//printf("!a %lld b %lld c %lld d %lld / x %lld y %lld\n", a, b, c, d, x, y);
printf("%lld\n", MM[0][0]);
}
Compilation message (stderr)
startrek.cpp: In function 'Mat operator*(const Mat&, const Mat&)':
startrek.cpp:20:16: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<std::vector<long long int> >::size_type' {aka 'long unsigned int'} [-Wsign-compare]
20 | for(int i=0; i<p.size(); i++) for(int j=0; j<q[0].size(); j++)
| ~^~~~~~~~~
startrek.cpp:20:46: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<long long int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
20 | for(int i=0; i<p.size(); i++) for(int j=0; j<q[0].size(); j++)
| ~^~~~~~~~~~~~
startrek.cpp:22:17: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<long long int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
22 | for(int k=0; k<p[0].size(); k++)
| ~^~~~~~~~~~~~
startrek.cpp: In function 'int main()':
startrek.cpp:140:7: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
140 | scanf("%d%lld", &N, &D);
| ~~~~~^~~~~~~~~~~~~~~~~~
startrek.cpp:145:8: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
145 | scanf("%d%d", &u, &v);
| ~~~~~^~~~~~~~~~~~~~~~
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |