比赛传送门
作者: fn
签到题
I题 xay loves or xay喜欢或运算
题目大意
给定
x
x
x 和
s
s
s ,计算有多少正整数
y
y
y 满足
x
or
y
=
s
x \operatorname{or} y=s
xory=s
考察内容
位运算
分析
对s和x上的每一个二进制位 ,
- x上为0,不影响答案;
- x上为1且s上为0,无解;
- x上和s上都为1,则答案乘二。
特判:x=s时会计算y=0的情况,这时候答案要减一。
#include<bits/stdc++.h>
#define ll long long
using namespace std;
int main(){
ios::sync_with_stdio(0); cin.tie(0);
ll x,s,ans=1,c=0;
cin>>x>>s;
if(x==s) c=1;
while(x || s){
if(x&1){
if((s&1)==0){
cout<<"0"<<endl;
return 0;
}
else{
ans<<=1;
}
}
x>>=1;
s>>=1;
}
cout<<ans-c<<endl;
return 0;
}
基本题
H题 xay loves count xay爱数数
题目大意
给定一个长度为
n
n
n 的数组
a
a
a ,计算有多少个三元组
(
i
,
j
,
k
)
(i, j, k)
(i,j,k) 满足
a
i
∗
a
j
=
a
k
a_i * a_j = a_k
ai∗aj=ak
考察内容
枚举
分析
枚举
a
k
a_k
ak ,然后再遍历
1
,
2
,
3
,
.
.
.
,
a
k
1 ,2, 3, ... , \sqrt{a_k}
1,2,3,...,ak 找
a
i
a_i
ai 就能确定
a
j
a_j
aj
#include<bits/stdc++.h>
using namespace std;
int n,a[1000005],t[1000005],qk,nt[1000005];
long long ans;
int main(){ // AC
scanf("%d",&n);
for(int i=1;i<=n;i++) {
scanf("%d",&a[i]);
t[a[i]]++;
}
for(int i=1,l=0;i<=1000000;i++) {
if(t[i]>0) {
nt[l]=i;
l=i;
}
}
for(int k=1;k<=n;k++) {
qk=sqrt(a[k]);
for(int i=nt[0],j;i!=0&&i<=qk;i=nt[i]) {
j=a[k]/i;
if(a[k]==j*i&&t[j]>0) {
if(i==j) ans+=t[i]*t[j];
else ans+=t[i]*t[j]*2;
}
}
}
printf("%lld",ans);
return 0;
}
进阶题
F题 xay loves trees xay喜欢树
题目大意
有两棵根结点为1的树,都有
n
n
n 个节点。 你需要找到
{
1
,
2
,
⋯
,
n
}
\{1,2, \cdots, n\}
{1,2,⋯,n} 的最大子集,使:
- 在第一棵树上,集合是连通的,对于集合中的任意两点 u u u , v v v ,其中一个 u u u 或 v v v 是另一个的祖先。
- 在第二棵树中,集合中的任意两点都不是对方的祖先。
输出集合中的元素个数的最大值。
考察内容
树状数组,倍增,dfs,主席树(可持久化线段树)
分析
#include<bits/stdc++.h>
using namespace std;
const int N=3e5+1e3+7;
int T,n;
vector<int>g[N],h[N];
int dc,st[N],ed[N],rev[N];
void dfs(int x,int f)
{
st[x]=++dc;
rev[dc]=x;
for(auto v:h[x])
{
if(v==f)
continue;
dfs(v,x);
}
ed[x]=dc;
}
set<int>s;
vector<int>del[N];
int ans,last;
int to[N];
void calc(int x,int f)
{
int lst=last;
while(s.size())
{
int ok=1;
auto it=s.lower_bound(st[x]);
if(it!=s.end()&&*it<=ed[x])
ok=0;
else if(it!=s.begin())
{
it--;
if(*it<=st[x]&&st[x]<=ed[rev[*it]])
ok=0;
}
if(ok)
break;
s.erase(st[last]);
del[x].push_back(st[last]);
last=to[last];
}
s.insert(st[x]);
ans=max(ans,(int)s.size());
for(auto v:g[x])
{
if(v==f)
continue;
to[x]=v;
calc(v,x);
}
s.erase(st[x]);
for(auto p:del[x])
s.insert(p);
last=lst;
}
int main()
{
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
g[i].clear(),h[i].clear(),del[i].clear();
ans=0;
for(int i=1;i<n;i++)
{
int u,v;
scanf("%d%d",&u,&v);
g[u].push_back(v);
g[v].push_back(u);
}
for(int i=1;i<n;i++)
{
int u,v;
scanf("%d%d",&u,&v);
h[u].push_back(v);
h[v].push_back(u);
}
last=1;
dc=0;
dfs(1,0);
s.clear();
calc(1,0);
printf("%d\n",ans);
}
}