# 5.30联考题解

A. 给出n个m维空间中的点，对于点$A\left({x}_{0},{x}_{1}....{x}_{m-1}\right),B\left({y}_{0},{y}_{1}....{y}_{m-1}\right)$$A(x_0,x_1....x_{m-1}),B(y_0,y_1....y_{m-1})$ $\left(0<={x}_{i},{y}_{i}<4\right)$$(0<=x_i,y_i<4)$，两点的距离定义为$\sum _{i=0}^{m-1}|{x}_{i}-{y}_{i}|$$\sum_{i=0}^{m-1}|x_i-y_i|$，求距离为0~3m中每个值的点对数量

$h\left[i\right]$$h[i]$表示有多少个点转化成四进制为$i$$i$

${a}_{0}={f}_{0}\ast {g}_{0}+{f}_{1}\ast {g}_{1}+{f}_{2}\ast {g}_{2}+{f}_{3}\ast {g}_{3}$$a_0=f_0*g_0+f_1*g_1+f_2*g_2+f_3*g_3$
${a}_{1}={f}_{0}\ast {g}_{1}+{f}_{1}\ast {g}_{0}+{f}_{1}\ast {g}_{2}+{f}_{2}\ast {g}_{1}+{f}_{2}\ast {g}_{3}+{f}_{3}\ast {g}_{2}$$a_1=f_0*g_1+f_1*g_0+f_1*g_2+f_2*g_1+f_2*g_3+f_3*g_2$
${a}_{2}={f}_{0}\ast {g}_{2}+{f}_{1}\ast {g}_{3}+{f}_{2}\ast {g}_{0}+{f}_{3}\ast {g}_{1}$$a_2=f_0*g_2+f_1*g_3+f_2*g_0+f_3*g_1$
${a}_{3}={f}_{0}\ast {g}_{3}+{f}_{3}\ast {g}_{0}$$a_3=f_0*g_3+f_3*g_0$

code：

#include<set>
#include<map>
#include<deque>
#include<queue>
#include<stack>
#include<cmath>
#include<ctime>
#include<bitset>
#include<string>
#include<vector>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<climits>
#include<complex>
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;

{
char c; while(!((c=getchar())>='0'&&c<='9'));
x=c-'0';
while((c=getchar())>='0'&&c<='9') (x*=10)+=c-'0';
}
const int maxn = 1<<18;

void fwt(ll a[],ll f[],ll g[],int N)
{
if(N==1) { a[0]=f[0]*g[0];return; }
int n=N/4;
ll u[n],v[n],ft[n],gt[n];

for(int i=0;i<n;i++) ft[i]=f[i]+f[i+n]+f[i+2*n]+f[i+3*n];
for(int i=0;i<n;i++) gt[i]=g[i]+g[i+n]+g[i+2*n]+g[i+3*n];
fwt(u,ft,gt,n);

for(int i=0;i<n;i++) ft[i]=f[i]-f[i+n]+f[i+2*n]-f[i+3*n];
for(int i=0;i<n;i++) gt[i]=g[i]-g[i+n]+g[i+2*n]-g[i+3*n];
fwt(v,ft,gt,n);

for(int i=0;i<n;i++) a[2*n+i]=(u[i]+v[i])>>1,a[n+i]=(u[i]-v[i])>>1;

for(int i=0;i<n;i++) ft[i]=f[i]+f[i+3*n];
for(int i=0;i<n;i++) gt[i]=g[i]+g[i+3*n];
fwt(u,ft,gt,n);

for(int i=0;i<n;i++) ft[i]=f[i]-f[i+3*n];
for(int i=0;i<n;i++) gt[i]=g[i]-g[i+3*n];
fwt(v,ft,gt,n);

for(int i=0;i<n;i++)
{
a[3*n+i]=(u[i]-v[i])>>1;
a[n+i]-=a[3*n+i];
}
for(int i=0;i<n;i++) a[i]=(u[i]+v[i])>>1;

for(int i=0;i<n;i++) ft[i]=f[n+i];
for(int i=0;i<n;i++) gt[i]=g[n+i];
fwt(u,ft,gt,n);

for(int i=0;i<n;i++) a[i]+=u[i];

for(int i=0;i<n;i++) ft[i]=f[2*n+i];
for(int i=0;i<n;i++) gt[i]=g[2*n+i];
fwt(v,ft,gt,n);

for(int i=0;i<n;i++)
{
a[i]+=v[i];
a[2*n+i]-=a[i];
}
}
int n,m;
ll a[maxn],f[maxn],g[maxn];
ll ans[maxn];

int main()
{
freopen("space.in","r",stdin);
freopen("space.out","w",stdout);

for(int i=1;i<=n;i++)
{
int now=0;
for(int j=0;j<m;j++)
{
now|=x<<j*2;
}
f[now]++,g[now]++;
}
fwt(a,f,g,1<<m*2);

for(int i=0;i<(1<<m*2);i++)
{
int dis=0;
for(int j=0;j<m;j++) dis+=i>>j*2&3;
ans[dis]+=a[i];
}
for(int i=0;i<=3*m;i++) printf("%lld%c",ans[i],i!=3*m?' ':'\n');

return 0;
}


B.

$f\left[i\right]\left[mask\right]$$f[i][mask]$表示处理到第$i$$i$条边，前$i-1$$i-1$条边已经确定了是否存在，$mask$$mask$是一个极大联通块的概率（这里极大联通块的定义为不能在往点集中添加点使得这些点仍然两辆联通）

$j$$j$不包含$u,v$$u,v$$f\left[i+1\right]\left[j\right]=f\left[i\right]\left[j\right]$$f[i+1][j]=f[i][j]$，这条边是否存在与这个联通块无关
$j$$j$包含$u,v$$u,v$中的一个，这条边一定不存在，$f\left[i+1\right]\left[j\right]=f\left[i\right]\left[j\right]\ast {p}_{i}$$f[i+1][j]=f[i][j]*p_i$

$j$$j$同时包含$u,v$$u,v$，枚举$j$$j$的子集$k$$k$$f[i+1][j]=f[i][j]+\sum_{k,k包含u不包含v }\ \ \ \ \ f[i][k]*f[i][j-k]*(1-p_i)/t$

code：

#include<set>
#include<map>
#include<deque>
#include<queue>
#include<stack>
#include<cmath>
#include<ctime>
#include<bitset>
#include<string>
#include<vector>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<climits>
#include<complex>
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;

const int maxn = 14;
const int maxm = 95;
const double eps = 1e-15;

int n,m,al,el=(1<<20)-1;
struct edge
{
int x,y,c;
double pi;
friend inline bool operator <(const edge x,const edge y){return x.c<y.c;}
}e[maxm];
double pe[5][1<<20];
struct data
{
int ei[5];
void add(int i) { ei[i/20]|=1<<(i%20); }
friend inline data operator &(const data &a,const data &b)
{
data re;
for(int i=0;i<5;i++) re.ei[i]=a.ei[i]&b.ei[i];
return re;
}
double cal()
{
double r=1.0;
for(int i=0;i<5;i++) r=r*pe[i][ei[i]];
return r;
}

double ans;

int main()
{
freopen("bridge.in","r",stdin);
freopen("bridge.out","w",stdout);

scanf("%d%d",&n,&m); al=(1<<n)-1;

for(int i=0;i<=al;i++) to3[i]=to3[i>>1]*3+(i&1);
for(int i=0;i<5;i++) for(int j=0;j<=el;j++) pe[i][j]=1.0;
for(int i=0;i<m;i++)
{
scanf("%d%d%d",&e[i].x,&e[i].y,&e[i].c); e[i].x--,e[i].y--;
scanf("%lf",&e[i].pi);
if(e[i].x==e[i].y) { i--;m--;continue; }
}
sort(e,e+m);
for(int i=0;i<m;i++)
{
for(int S=al^(1<<e[i].x),s=S;;s=(s-1)&S)
{
if(!s)break;
}
for(int S=al^(1<<e[i].y),s=S;;s=(s-1)&S)
{
if(!s)break;
}

for(int t=i/20,j=i%20,S=el^(1<<j),s=S;;s=(s-1)&S)
{
pe[t][s|1<<j]*=e[i].pi;
if(!s)break;
}
}

for(int i=0;i<n;i++) g[0][1<<i]=1.0;
for(int i=0;i<m;i++)
{
for(int j=0;j<=al;j++) if((j>>e[i].x&1)&&!(j>>e[i].y&1)&&g[i][j]>eps)
ans+=g[i][j]*(1-e[i].pi)*e[i].c;

for(int j=0;j<=al;j++)
{
if(!(j>>e[i].x&1)&&!(j>>e[i].y&1)) g[i+1][j]=g[i][j];
else if((j>>e[i].x&1)^(j>>e[i].y&1)) g[i+1][j]=g[i][j]*e[i].pi;
else
{
g[i+1][j]=g[i][j];
for(int S=j^(1<<e[i].x)^(1<<e[i].y),s=S;;s=(s-1)&S)
{
int x=s|1<<e[i].x,y=(S^s)|1<<e[i].y;
if(g[i][x]>eps&&g[i][y]>eps)
{
double tc=(ei[x]&ei[y]&now).cal();
if(tc>eps) g[i+1][j]+=g[i][x]*g[i][y]/tc*(1-e[i].pi);
}
if(!s)break;
}
}
}
}

printf("%.6lf\n",ans);

return 0;
}


C.

code：

#include<set>
#include<map>
#include<deque>
#include<queue>
#include<stack>
#include<cmath>
#include<ctime>
#include<bitset>
#include<string>
#include<vector>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<climits>
#include<complex>
#include<iostream>
#include<algorithm>
#define ll long long
#define pb push_back
#define mp make_pair
#define fir first
#define sec second
#define SZ(x) ((int)x.size())
#define End(x) (x.begin()+SZ(x)-1)
using namespace std;

{
int f=1; char c;
while(!((c=getchar())>='0'&&c<='9')) if(c=='-') f=-1;
x=c-'0';
while((c=getchar())>='0'&&c<='9') (x*=10)+=c-'0';
if(f==-1) x=-x;
}
const int maxn = 410000;

ll ans;
int n,m,K;
pair<int,int>xi[maxn];
int dis[maxn];
struct List
{
int fa[maxn];
void init(){for(int i=1;i<=n;i++) fa[i]=i;}
int findfa(const int x){return fa[x]==x?x:fa[x]=findfa(fa[x]);}
}L,R;

int vi[maxn][2],nowd[maxn];
vector<int>V[maxn<<1];

int qend(int x,int dir)
{
int ix=vi[x][dir];
return SZ(V[ix])?(*End(V[ix])):0;
}
void Run(int x,int dir)
{
int ix=vi[x][dir],ix2=vi[x][!dir];
int o=0;
if(SZ(V[ix])) o=(*End(V[ix])),V[ix].erase(End(V[ix]));
ans+=nowd[x]-o*2;
V[ix2].pb(nowd[x]-o);
}
void merge(int x,int y)
{
nowd[x]+=nowd[y];

int sx,sy;
int &ix0=vi[x][0],&iy0=vi[y][0]; if(SZ(V[ix0])<SZ(V[iy0])) swap(ix0,iy0);
sx=SZ(V[ix0]),sy=SZ(V[iy0]);
for(int i=0;i<sy;i++) V[ix0][sx-(sy-i)]+=V[iy0][i];

int &ix1=vi[x][1],&iy1=vi[y][1]; if(SZ(V[ix1])<SZ(V[iy1])) swap(ix1,iy1);
sx=SZ(V[ix1]),sy=SZ(V[iy1]);
for(int i=0;i<sy;i++) V[ix1][sx-(sy-i)]+=V[iy1][i];
}

set< pair<int,int> >S;
set< pair<int,int> >::iterator it;

int main()
{
freopen("friend.in","r",stdin);
freopen("friend.out","w",stdout);

n+=m;
sort(xi+1,xi+n+1);

L.init(); R.init();
for(int i=2;i<=n;i++)
{
vi[i][0]=i,vi[i][1]=n+i;
nowd[i]=xi[i].fir-xi[i-1].fir;
dis[i]=dis[i-1]+nowd[i];
if(xi[i-1].sec^xi[i].sec) S.insert(mp(nowd[i],i));
}

while(K--)
{
it=S.begin(); pair<int,int>temp=(*it); S.erase(it);
int x=temp.sec,y=L.findfa(x-1),dir=!xi[y].sec;
if(R.findfa(x)!=x||!y||nowd[x]-qend(x,dir)*2!=temp.fir) {K++;continue;}
Run(x,dir);

L.fa[y]=y-1,R.fa[y]=y+1;
L.fa[x]=x-1,R.fa[x]=x+1;
if(!L.findfa(y-1)||!R.findfa(x+1)) continue;

merge(x,y);
y=R.findfa(x+1);
merge(y,x),x=y;

y=L.findfa(x-1),dir=!xi[y].sec;
if(xi[x].sec^xi[y].sec) S.insert(mp(nowd[x]-qend(x,dir)*2,x));
}
printf("%lld\n",ans);

return 0;
}


• 广告
• 抄袭
• 版权
• 政治
• 色情
• 无意义
• 其他

120