统计一个包含所有点的最小子树长度*2
a[k]=a[0];
for(int i=0;i<k;i++)ans+=dis(a[i],a[i+1]);
子集dp
void sos(){
for(int i=0;i<(1<<N);i++)
f[i]=w[i];
for(int i=0;i<N;i++)
for(int st=0;st<(1<<N);st++)
if(st&(1<<i)) f[st]+=f[st^(1<<i)];
}
容斥dfs版
dfs(int beg,set S,int sym)
{
ans+=num(S)*sym;
for(int i=beg;i<=n;i++)
dfs(i,S∩A[i],sym*-1);
}
for(int i=1;i<=n;i++)
dfs(i,A[i],1);
挺好的lucas板子
struct Lucas
{
LL p;
LL fa[MO],inv[MO];//阶乘和逆元,注意空间大小
void init(LL _p)
{
p=_p;
fa[0]=1;
for(int i=1;i<p;i++)
{
fa[i]=fa[i-1]*i%p;
//cout<<"i "<<i;
inv[i]=qp(i,p-2,p);
//cout<<"i "<<i;
}
}
LL c(LL n,LL m)//小组合数取模
{
if(n==m||m==0)
return 1;
if(m>n)
return 0;
return fa[n]*inv[fa[n-m]*fa[m]%p]%p;
}
LL lucas(LL n,LL m)//大组合数取模
{
if(n==m||m==0)
return 1;
if(m>n)
return 0;
return c(n%p,m%p)*lucas(n/p,m/p)%p;
}
}lu;
线段树二分得小于某数最前位置
int query(int now,int L,int R,int i,int j,int d)
{
if(L==R)//达到端点,直接返回
{
if(minv[now]<=d)
return L;
else
return -1;
}
if(i<=L && R<=j)//对于已经包含了的情况,直接判断,也是吧*logn变成+logn的关键
if(minv[now]>d)
return -1;
int m=(L+R)>>1;
if(j<=m)
return query(lc[now],L,m,i,j,d);
if(i>=m+1)
return query(rc[now],m+1,R,i,j,d);//正常的筛出小区间
int t1=query(lc[now],L,m,i,j,d);//先左子树
if(t1!=-1)
return t1;
return query(rc[now],m+1,R,i,j,d);//左子树不行才弄右子树
}