省选模拟30
很不如意,啥也不是
考场上由于题面的pdf是一道一道的没有整合起来,于是我就先看的第三题,然后就弃掉了
心态有些爆炸,但是还是强行的给拉回来了
看T1,明显的感觉到是转化题意,但是不知道怎么办,于是只能硬想,想破头皮走了
T2一开始不知道啥叫对称差,后来想了想就是并集减交集,拿了40分
T1
按位考虑,发现如果这一位是1的话,那么会有\(2^{n-1}\)种方案使得这一位是一,0的任意选,1的选奇数个
那么题意就转化为,一堆数或起来能得到的数的个数
按照最高不同位分开,分类讨论
选两个小于最高位的数,无论如何都不会得到其他的数,就是这里面数的数量
选一个大于的数,如果和下面的数或,也可以得到下面的数的数量
如果是两个上面的数,那么找到下一个1,后面的就任意了,最后取个min就好了
AC_code
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define fo(i,x,y) for(int i=(x);i<=(y);i++)
#define fu(i,x,y) for(int i=(x);i>=(y);i--)
int read(){
int s=0,t=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')t=-1;ch=getchar();}
while(isdigit(ch)){s=s*10+ch-'0';ch=getchar();}
return s*t;
}
const int N=105;
int T,n,l,r,ans;
signed main(){
freopen("a.in","r",stdin);
freopen("a.out","w",stdout);
T=read();
while(T--){
n=read();l=read();r=read();ans=0;
if(n==1){printf("%lld\n",r-l+1);continue;}
if(l==r){printf("1\n");continue;}
fu(i,60,0){
if(!(r>>i&1))continue;
if(l>>i&1){
r^=(1ll<<i);
l^=(1ll<<i);
continue;
}
ans+=(1ll<<i)-l;
// cerr<<ans<<endl;
int now=i-1;
while(now>=0&&(!((r>>now)&1)))now--;
// cerr<<now<<" "<<(r>>now&1)<<endl;
ans+=min((1ll<<i)-l+(1ll<<now+1),(1ll<<i));
break;
}
printf("%lld\n",ans);
}
return 0;
}
T2
如果给你一颗树,那么答案就是\(n \choose 4\)
因为每个四元组只有一种划分可能
那么我们接下来的任务就是求交集
首先两条链没有交集,那么这两条链一定会被另外一条链链接
于是可以利用这条链上的点和边进行容斥,边减去点
交集的话,就是边边-边点+点点
可以枚举第一颗树删除啥,然后染色,在第二颗统计就行了
AC_code
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define fo(i,x,y) for(int i=(x);i<=(y);i++)
#define fu(i,x,y) for(int i=(x);i>=(y);i--)
int read(){
int s=0,t=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')t=-1;ch=getchar();}
while(isdigit(ch)){s=s*10+ch-'0';ch=getchar();}
return s*t;
}
const int N=2005;
int n,ans;
int c[N][N],col[N];
struct TREE{
struct E{int to,nxt;}e[N*2];
int head[N],rp;
void add_edg(int x,int y){e[++rp].to=y;e[rp].nxt=head[x];head[x]=rp;}
void add(int x,int y,int id){add_edg(x,y);add_edg(y,x);}
int siz[N][3],fa[N];
void dfs1(int x,int f,int v){
col[x]=-1;if(x<=n)col[x]=v;
for(int i=head[x];i;i=e[i].nxt){
int y=e[i].to;
if(y==f)continue;
dfs1(y,x,v);
}
}
void dfs2(int x,int f){
siz[x][0]=siz[x][1]=siz[x][2]=0;
if(~col[x])siz[x][col[x]]++;fa[x]=f;
for(int i=head[x];i;i=e[i].nxt){
int y=e[i].to;
if(y==f)continue;
dfs2(y,x);
fo(j,0,2)siz[x][j]+=siz[y][j];
}
}
}t1,t2;
int d[3][3];
signed main(){
freopen("b.in","r",stdin);
freopen("b.out","w",stdout);
n=read();
fo(i,0,2*n){
c[i][0]=1;
fo(j,1,i)c[i][j]=c[i-1][j-1]+c[i-1][j];
}
fo(i,1,2*n-3)t1.add(read(),read(),i);
fo(i,1,2*n-3)t2.add(read(),read(),i);
t1.dfs2(1,0);
ans+=c[n][4]*2;int res=0;
fo(x,n+1,2*n-2){
col[x]=-1;
for(int i=t1.head[x],now=0;i;i=t1.e[i].nxt,now++){
int z=t1.e[i].to;
t1.dfs1(z,x,now);
}
t2.dfs2(1,0);
fo(y,n+1,2*n-2){
fo(i,0,2)d[0][i]=t2.siz[1][i]-t2.siz[y][i];
for(int i=t2.head[y],now=0;i;i=t2.e[i].nxt){
int z=t2.e[i].to;
if(z==t2.fa[y])continue;
now++;fo(j,0,2)d[now][j]=t2.siz[z][j];
}
fo(i,0,2)fo(j,i+1,2)fo(k,0,2)fo(l,k+1,2){
res+=c[d[i][k]][2]*c[d[j][l]][2];
res+=c[d[i][l]][2]*c[d[j][k]][2];
}
}
}
fo(x,n+1,2*n-2){
for(int i=t1.head[x],now=0;i;i=t1.e[i].nxt,now++){
int z=t1.e[i].to;
t1.dfs1(z,x,now);
}
t2.dfs2(1,0);
fo(y,n+1,2*n-2){
fo(i,0,2){
d[0][i]=t2.siz[1][i]-t2.siz[y][i];
d[1][i]=t2.siz[y][i];
}
fo(i,0,1)fo(j,i+1,1)fo(k,0,2)fo(l,k+1,2){
res-=c[d[i][k]][2]*c[d[j][l]][2];
res-=c[d[i][l]][2]*c[d[j][k]][2];
}
}
}
fo(x,n+1,2*n-2){
t1.dfs1(x,t1.fa[x],0);t1.dfs1(t1.fa[x],x,1);
t2.dfs2(1,0);
fo(y,n+1,2*n-2){
fo(i,0,1)d[0][i]=t2.siz[1][i]-t2.siz[y][i];
for(int i=t2.head[y],now=0;i;i=t2.e[i].nxt){
int z=t2.e[i].to;
if(z==t2.fa[y])continue;
now++;fo(j,0,1)d[now][j]=t2.siz[z][j];
}
fo(i,0,2)fo(j,i+1,2)fo(k,0,1)fo(l,k+1,1){
res-=c[d[i][k]][2]*c[d[j][l]][2];
res-=c[d[i][l]][2]*c[d[j][k]][2];
}
}
}
fo(x,n+1,2*n-2){
t1.dfs1(x,t1.fa[x],0);t1.dfs1(t1.fa[x],x,1);
t2.dfs2(1,0);
fo(y,n+1,2*n-2){
fo(i,0,2){
d[0][i]=t2.siz[1][i]-t2.siz[y][i];
d[1][i]=t2.siz[y][i];
}
fo(i,0,1)fo(j,i+1,1)fo(k,0,1)fo(l,k+1,1){
res+=c[d[i][k]][2]*c[d[j][l]][2];
res+=c[d[i][l]][2]*c[d[j][k]][2];
}
}
}
ans-=2*res;
printf("%lld",ans);
return 0;
}
T3
不会
QQ:2953174821