xgc的模拟赛
T1
Description
正方形有
定义点为零维基础图形,线段为一维基础图形,正方形为二维基础图形,正方体为三维基础图形...,问一个
多次询问,答案对
Input
第一行一个正整数
下接
Output
输出
Sample Input
4
3 0
3 1
3 2
3 3
Sample Output
8
12
6
1
Hint
对于全部数据,
存在
存在
存在
存在
题解
原题链接
解法一
由于都是基础图形,那么直接将边的长度看作
在
解法二
由点动成线,线动成面,面动成体这种规律中可以得知,如果要将
以
代码
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=1e5+5,mod=998244353;
typedef long long ll;
ll fac[N],inv[N];
inline ll power(ll a,ll b)
{
ll sum=1;
while(b)
{
if(b&1)sum=sum*a%mod;
a=a*a%mod;b>>=1;
}
return sum;
}
inline ll C(ll n,ll m){return fac[n]*inv[m]%mod*inv[n-m]%mod;}
int main()
{
freopen("a.in","r",stdin);
freopen("a.out","w",stdout);
fac[0]=inv[0]=1;
for(int i=1;i<=N-5;i++)fac[i]=fac[i-1]*i%mod;
inv[N-5]=power(fac[N-5],mod-2);
for(int i=N-6;i>=1;i--)inv[i]=inv[i+1]*(i+1)%mod;
int T;scanf("%d",&T);
while(T--)
{
ll n,m;
scanf("%lld%lld",&n,&m);
printf("%lld\n",C(n,m)*power(2,n-m)%mod);
}
return 0;
}
T2
Description
从
现在希望求所有点的最小距离和,并输出这个值除以
Input
第一行一个数
接下来
Output
一行一个实数表示答案,保留
Sample Input
4
1 2 1
1 3 1
3 4 2
Sample Output
3.0000000000
Hint
对于所有测试点,边权
对于测试点
对于测试点
对于测试点
对于测试点
题解
考虑对于一个节点求出它的儿子的遍历的优先顺序。
考虑对于一个拥有两个儿子的节点,遍历节点的优先顺序,假设把
因此按照
代码
#include<vector>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=1e5+5;
vector<int>vec[N];
int arrive[N],last[N],sum[N],tot[N],w[N],len,n;
struct edge{int x,y,d,next;}a[N<<1];
inline void ins(int x,int y,int d)
{
len++;a[len].x=x;a[len].y=y;a[len].d=d;
a[len].next=last[x];last[x]=len;
}
inline bool cmp(int x,int y){return ((double)tot[x]/(double)sum[x]>(double)tot[y]/(double)sum[y]);}
inline void dfs(int x,int fa)
{
tot[x]=1;
for(int k=last[x];k;k=a[k].next)
{
int y=a[k].y;
if(y==fa)continue;
w[y]=a[k].d;
sum[y]=w[y]*2;
vec[x].push_back(y);
dfs(y,x);
tot[x]+=tot[y];
sum[x]+=sum[y];
}
sort(vec[x].begin(),vec[x].end(),cmp);
}
inline int work(int x)
{
int ns=0;
for(int k=0;k<vec[x].size();k++)
{
int y=vec[x][k];
arrive[y]=arrive[x]+ns+w[y];
ns+=work(y)+w[y]*2;
}
return ns;
}
inline int read()
{
int x=0,f=1;char c=getchar();
while(c<'0' || c>'9'){if(c=='-')f=-1;c=getchar();}
while(c>='0' && c<='9')x=x*10+c-'0',c=getchar();
return x*f;
}
int main()
{
freopen("b.in","r",stdin);
freopen("b.out","w",stdout);
n=read();
for(int i=1;i<=n-1;i++)
{
int x,y,d;
x=read();y=read();d=read();
ins(x,y,d);ins(y,x,d);
}
dfs(1,0);
work(1);
double ans=0;
for(int i=1;i<=n;i++)ans+=(double)arrive[i];
printf("%.10lf\n",ans/(n-1));
return 0;
}
T3
原题链接
代码
//代码参考lzy
#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N=5e5+10;
inline int read()
{
int x=0,f=1;char c=getchar();
while(c<'0' || c>'9'){if(c=='-')f=-1;c=getchar();}
while(c>='0' && c<='9')x=x*10+c-'0',c=getchar();
return x*f;
}
int n,m,t,tot,len,in[N],out[N],dep[N],last[N],fa[N][20];
struct edge{int y,next;}a[N<<1];
void ins(int x,int y)
{
len++;a[len].y=y;
a[len].next=last[x];last[x]=len;
}
void dfs(int x)
{
in[x]=++tot;
for(int k=last[x];k;k=a[k].next)
{
int y=a[k].y;
if(y==fa[x][0])continue;
fa[y][0]=x;dep[y]=dep[x]+1;
for(int i=1;i<=t;i++)
fa[y][i]=fa[fa[y][i-1]][i-1];
dfs(y);
}
out[x]=tot;
}
struct seg{int l,r;}Line[N<<1];
inline bool cmp(seg n1,seg n2){return n1.l<n2.l;}
inline void jump(int &x,int k)
{
for(int i=0;k;i++)
if((k>>i)&1)x=fa[x][i],k^=1<<i;
}
inline int dis(int x,int y)
{
if(dep[x]<dep[y])swap(x,y);
int k=dep[x]-dep[y],s=k;
jump(x,k);
if(x==y)return s-1;
for(int i=t;i>=0;i--)
if(fa[x][i]!=fa[y][i])
s+=1<<(i+1),x=fa[x][i],y=fa[y][i];
return s+1;
}
void cover(int x,int y)
{
int z=dis(x,y);
if(dep[x]>dep[y])
{
jump(x,(z+1)>>1);
if(in[x]>1)Line[++len]=(seg){1,in[x]-1};
if(out[x]<n)Line[++len]=(seg){out[x]+1,n};
}
else
{
jump(y,z>>1);
Line[++len]=(seg){in[y],out[y]};
}
}
int main()
{
freopen("c.in","r",stdin);
freopen("c.out","w",stdout);
n=read();m=read();t=log2(n);
for(int i=1;i<n;i++)
{
int x,y;
x=read(),y=read();
ins(x,y),ins(y,x);
}
memset(fa[0],0,sizeof(fa[0]));
dep[1]=1;fa[1][0]=0;
dfs(1);
while(m--)
{
int x,y,k,sum=0,pos=0;
k=read();x=read();len=0;
while(--k)
{
y=read();
cover(x,y);
}
sort(Line+1,Line+len+1,cmp);
for(int i=1;i<=len;i++)
{
if(pos<Line[i].l)
{
sum+=Line[i].r-Line[i].l+1;
pos=Line[i].r;
}
else if(pos<Line[i].r)
{
sum+=Line[i].r-pos;
pos=Line[i].r;
}
}
printf("%d\n",n-sum);
}
return 0;
}