17.10.28B组总结
T1
一道数论题,某ZYS大佬推了两个多小时,考场切掉,然而我并不想花时间在50分上(大众分30~50),正解那一波式子真的烦,大致如下:
我们设f[i]表示i层k叉数的数量,则
f[i]=ki−1k−1
那么我们发现
ans=∑i=0n−1(f[n−i+1]2−k∗f[n−i]2)∗i∗ki
代入得
ans=∑i=0n−1((kn−i+1−1k−1)2−k∗(kn−i−1k−1)2)∗i∗ki
化简一下就得到
ans=∑n−1i=0i∗ki−i∗k2∗n−i+1k−1
算了,不说这么多了,总之就是:
k2∗n−k−(2n−1)∗kn∗(k−1)(k−1)3
记得用逆元。
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
using namespace std;
typedef long long ll;
const ll mo=998244353;
ll n,k,ans,t;
ll qsm(ll x,ll y)
{
ll z=1;
while (y)
{
if (y&1)
z=z*x%mo;
x=x*x%mo,y/=2;
}
return z;
}
int main( )
{
scanf("%lld%lld",&n,&k);
ans=((qsm(k,2*n)-k-(2*n-1)*qsm(k,n)%mo*(k-1)%mo+mo)%mo+mo)%mo;
t=qsm(k-1,3);
ans=ans*qsm(t,mo-2)%mo;
printf("%lld\n",ans);
}
T2
作为一道暴力都轻松a的题,不必多说。
看到数据b串仅有20位,于是乎很自然的想到了暴力,仅仅只有
O(2mn)
而已,但是看上去貌似过不了,纪中数据水呀。
#include <cstdio>
#include <iostream>
#include <cstring>
#define fo(i,a,b) for (int i=a;i<=b;i++)
using namespace std;
char a[100010],b[30],st[30];
int n,m,len,ans;
bool bz[100010];
inline void dfs(int x)
{
if (x>m)
{
len=0;
fo(i,1,m)
if (bz[i])
st[++len]=b[i];
fo(i,1,len/2)
if (st[i]!=st[len-i+1])
return;
int i=1,j=1;
fo(i,1,n)
{
if (a[i]==st[j])
j++;
if (j>len)
break;
}
if (j<=len)
return;
ans=max(ans,len);
return;
}
bz[x]=true,dfs(x+1);
bz[x]=false,dfs(x+1);
}
int main()
{
scanf("%s",a+1);
scanf("%s",b+1);
n=strlen(a+1);
m=strlen(b+1);
dfs(1);
printf("%d\n",ans);
}
T3
又是随机,考试直接弃疗(连暴力都不会打)。
然而事实告诉我们,不要畏惧他,它仅仅只是一个树形DP而已。
我们设
f[i,j]
表示现在在节点i走到节点j且满足i和j有边直接相连的期望长度。
可以得到
f[i,j]=1d[i]+∑k与i相连且k!=j1+f[k,i]+f[i,j]d[i]
(d[i]表示i的度数)
化简得
f[i,j]=d[i]+∑k与i相连且k!=jf[k,i]
接着设 1 为根,跑一遍 DFS,自下而上计算出所有的 f[i,fa[i]] 。
机智的我们又可以观察到
f[i,fa[i]]=∑j在i的子树内d[j]=size[i]∗2−1
那么很显然
f[i,fa[i]]+f[fa[i],i]=n∗2−2
于是就可以求出 f[fa[i],i] 了。
那么我们就可以设a[x]表示x到x的子树内的最大期望距离,b[x]表示x的子树内到x的最大期望距离,然后按照顺序把x的子树到x的距离排好,然后维护一个前缀max和后缀max就好了。
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#define N 100005
using namespace std;
int n,cnt,ans,last[N],d[N],f[N],g[N],a[N],b[N],c[N],mx1[N],mx2[N];
struct edge{int to,next;}e[N*2];
void insert2(int u,int v)
{
e[++cnt].to=v;e[cnt].next=last[u];last[u]=cnt;
e[++cnt].to=u;e[cnt].next=last[v];last[v]=cnt;
}
void dfs(int x,int fa)
{
int i,s=0,s1=0;
mx1[0]=mx2[s+1]=0;
f[x]=d[x];
for (i=last[x];i;i=e[i].next)
{
if(e[i].to==fa)continue;
dfs(e[i].to,x);
f[x]+=f[e[i].to];
a[x]=max(a[x],a[e[i].to]+g[e[i].to]);
b[x]=max(b[x],b[e[i].to]+f[e[i].to]);
}
for (i=last[x];i;i=e[i].next)
c[++s]=a[e[i].to]+g[e[i].to];
for (i=1;i<=s;i++)
{
mx1[i]=max(mx1[i-1],c[i]);
mx2[s-i+1]=max(mx2[s-i+2],c[s-i+1]);
}
for (i=last[x];i;i=e[i].next)
{
if (e[i].to==fa) continue;
ans=max(ans,b[e[i].to]+f[e[i].to]+max(mx1[(++s1)-1],mx2[s1+1]));
}
g[x]=n*2-f[x]-2;
}
int main()
{
scanf("%d",&n);
for (int i=1;i<n;i++)
{
int x,y;
scanf("%d%d",&x,&y);
insert2(x,y);
d[x]++;d[y]++;
}
dfs(1,0);
printf("%d.00000",ans);
return 0;
}