题目太长不粘贴了,链接在这:
CH Round #65 - MFOI杯水题欢乐赛 day2
题目链接 -> 密码:exdb
题解
T1算叶子之间的距离算成深度相加忘了减去LCA了,我傻X
T2不会,弃题,没学过SG函数
T3dfs10分,dp不会,我傻X
总结:10分滚粗,人弱就不该作死
T1题意:
给你两棵树,从a树中选两个不同叶子,b树中选两个不同的叶子,连接起来组成一个环,问所有不同方案这种环的大小总和是多少,边权为1。若选的叶子不同或者叶子相同但连接方式不同则视为不同方案。n<=100w。
记树的叶子间路径总数为A,叶子间路径总距离为B,叶子总数为C。
容易看出,a树中某两个叶子间的路径长度被计算了 (Cb−1)∗Cb 次,而 A=(C−1)∗C/2 ,然后对于所有路径求和,再加上连的边的长度,答案则是:
要除以2。
然后我们发现A可以用C在O(1)的时间里求出来,关键在B上。
这时候考虑每条边对B的贡献。很显然若v的子树中有k个叶子,则u-v边的贡献是 k∗(c−k)∗2 ,这样B就可以树形DP去O(n)求了。
总结:傻X题,我更傻X所以不会做
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
typedef long long LL;
const int SZ = 3000010;
const int INF = 1000000010;
const double eps = 1e-6;
const int mod = 1000000007;
const int ni = 500000004;
int head[SZ],nxt[SZ],tot = 1,to[SZ];
void build(int f,int t)
{
to[++ tot] = t;
nxt[tot] = head[f];
head[f] = tot;
}
LL sz[SZ],du[SZ],c;
void dfs(int u,int fa,LL a,LL &b)
{
if(du[u] == 1) sz[u] = 1;
for(int i = head[u];i;i = nxt[i])
{
int v = to[i];
if(v == fa) continue;
dfs(v,u,a,b);
sz[u] += sz[v];
b = (b + ((sz[v] * (c - sz[v])) % mod * 2) % mod) % mod;
}
}
LL a1,b1,a2,b2;
void init()
{
memset(head,0,sizeof(head));
memset(sz,0,sizeof(sz));
memset(du,0,sizeof(du));
tot = 1;
}
void init_tree(LL &a,LL &b,LL &c)
{
c = 0;
init();
int n;
scanf("%d",&n);
for(int i = 1;i < n;i ++)
{
int a,b;
scanf("%d%d",&a,&b);
build(a,b); build(b,a);
du[a] ++; du[b] ++;
}
for(int i = 1;i <= n;i ++)
if(du[i] == 1)
c ++;
a = c * (c - 1) % mod;
if(n == 2)
{
b = 2;
}
else
{
for(int i = 1;i <= n;i ++)
if(du[i] != 1)
{
dfs(i,0,a,b);
break;
}
}
}
int main()
{
// freopen("input.txt","r",stdin);
init_tree(a1,b1,c);
// printf("%lld %lld %lld\n",a1,b1,c);
init_tree(a2,b2,c);
// printf("%lld %lld %lld\n",a2,b2,c);
LL ans1 = (a1 * b2) % mod;
LL ans2 = (a2 * b1) % mod;
LL ans3 = (a1 * a2 * 2) % mod;
LL ans = (ans1 + ans2 + ans3) % mod;
printf("%lld",(ans * (LL)ni % mod ) % mod);
return 0;
}
/* 581299242 521290183 */
T2题意:
给你一棵有根树,一些节点上有蚂蚁,AB两人轮流把某一只蚂蚁往远离根的方向移动[1,d]的距离,问先手的A是否有必胜策略。多组询问。n,d<=100w
然后我不会做,SG函数能吃吗?还要有线段树合并?那是啥?
T3题意:
m个字符,组成长度为n的串,要求最长连续相同子段的长度不能大于k,问方案数。
m<=109 ,1<=k<=n<=100w
DP,推了半天没推出来…还是爆搜好写…