A. Ehab Fails to Be Thanos
题意
给你一个长度为 \(2n\) 的序列,重排该序列使得前一半和不等于后一半和。无解输出 \(-1\) 。
题解
显然如果所有数相等肯定无解,否则排序即可。
代码太丑不贴……
B. Ehab Is an Odd Person
题意
给你一个长度为 \(n\) 的序列 \(a_1,\dots,a_n\),若 \(a_i+a_j\) 为奇数你可以交换这两个数。求你能得到的字典序最小的序列。\(n\le 10^5\) 。
题解
显然如果所有数都是奇数或偶数答案为原数列。否则对于两个奇偶性相同的数我们可以藉由一个奇偶性不同的点交换,答案为排序后的序列。
code
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
inline int gi()
{
char c; int x=0,f=1;
for(;c<'0'||c>'9';c=getchar())if(c=='-')f=-1;
for(;c>='0'&&c<='9';c=getchar())x=(x<<1)+(x<<3)+c-'0';
return x*f;
}
const int N=1e5+5;
int n,a[N],sa[N],rk[N],sum1,sum2;
int main()
{
#ifndef ONLINE_JUDGE
freopen("b.in","r",stdin);
#endif
n=gi();
for(int i=1;i<=n;++i) a[i]=gi(),sum1+=(a[i]%2==0),sum2+=(a[i]%2);
if(sum1&&sum2) sort(a+1,a+1+n);
for(int i=1;i<=n;++i) printf("%d ",a[i]);
}
C. Ehab and a Special Coloring Problem
题意
构造一个长度为 \(n\) 的序列,使得下标互质的两个位置的数不等且最大值尽可能小。\(n\le 10^5\) 。
题解
直接跑筛法即可。
code
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
inline int gi()
{
char c; int x=0,f=1;
for(;c<'0'||c>'9';c=getchar())if(c=='-')f=-1;
for(;c>='0'&&c<='9';c=getchar())x=(x<<1)+(x<<3)+c-'0';
return x*f;
}
const int N=2e5+5;
int a[N];
bool p[N];
int main()
{
#ifndef ONLINE_JUDGE
freopen("c.in","r",stdin);
#endif
int n; scanf("%d",&n);
int cnt=0;
for(int i=2;i*i<=n;++i)
{
if(!p[i])
{
a[i]=++cnt;
for(int j=i*i;j<=n;j+=i) p[j]=true,a[j]=cnt;
}
}
for(int i=2;i<=n;++i) printf("%d ",a[i]?a[i]:++cnt);
}
D. Ehab and the Expected XOR Problem
题意
给你 \(n,x\) ,构造一个尽可能长的每个数 \(\le 2^n\) 的序列使得不存在子段的异或和为 \(0\) 或 \(x\) 。
\(1\le n\le 18, 1\le x < 2^{18}\)
题解
考虑原序列的前缀异或和 \(s_i\) ,条件转化为不存在 \(s_i \oplus s_j=x\) 和 \(s_i=s_j\) ,即只能出现最多一个 \(s_i\) 或 \(s_i\oplus x\) 。
code
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
inline int gi()
{
char c; int x=0,f=1;
for(;c<'0'||c>'9';c=getchar())if(c=='-')f=-1;
for(;c>='0'&&c<='9';c=getchar())x=(x<<1)+(x<<3)+c-'0';
return x*f;
}
const int N=3e5+5;
bool vis[N];
int v[N],cnt;
int main()
{
#ifndef ONLINE_JUDGE
freopen("d.in","r",stdin);
#endif
int n,x,lst=0;
scanf("%d%d",&n,&x);
vis[x]=true;
for(int i=1;i<(1<<n);++i)
if(!vis[i]) vis[i^x]=true,v[++cnt]=lst^i,lst=i;
printf("%d\n",cnt);
for(int i=1;i<=cnt;++i) printf("%d ",v[i]);
}
E. Ehab and the Expected GCD Problem
考虑排列的第一个数 。假如分解质因子后为 \(\prod p_i^{c_i}\),那么此时排列价值的最大值为 \(\sum c_i\)。
所以不同个数达到 \(\max\),\(\sum c_i\) 一定要达到 \(\max\),容易发现 \(\ge 5\) 的质因子不可能存在,因为 \(2<5\) ;而至多存在一个 \(3\) ,因为 \(2^3<3^2\)
设 \(f(i,j,0/1)\) 表示到第 \(i\) 个数,有 \(j\) 个因子 \(2\),有 \(0/1\) 个因子 \(3\)。
直接转移即可。
#include<bits/stdc++.h>
int f[2][25][3];
const int Mod=1e9+7;
inline void upd(int& x, int y)
{
x=(x+y>Mod?x+y-Mod:x+y);
}
#define mul(x,y) (1ll*(x)*(y)%Mod)
int main()
{
int n,m;
scanf("%d",&n);
for(m=1;(1<<m)<=n;++m);--m;
f[1][m][0]=1;
if((1<<(m-1))*3<=n) f[1][m-1][1]=1;
for (int i=2;i<=n;i++)
{
memset(f[i&1],0,sizeof(f[i&1]));
for (int j=0;j<=m;j++)
for(int k=0;k<=1;++k)
{
int x=(1<<j)*(k?3:1);
upd(f[i&1][j][k],mul(f[~i&1][j][k],n/x-i+1));
upd(f[i&1][j][k],mul(f[~i&1][j+1][k],n/x-(n/(x*2))));
upd(f[i&1][j][k],mul(f[~i&1][j][k+1],n/x-(n/(x*3))));
}
}
printf("%d",f[n&1][0][0]);
}
F. Ehab and the Big Finale
题意
交互题。给你一棵 \(n\) 个节点的树。有一个节点 \(x\) (不给出),你可以查询某一节点到 \(x\) 的距离或某一节点到 \(x\) 路径上的下一个节点(该节点必须是 \(x\) 的祖先)。用不超过 \(36\) 次询问找到 \(x\) 。
\(n\le 2\cdot 10^5\) 。
题解
树链剖分。
考虑当前节点 \(u\) 为链顶的重链,通过一次询问找到 \(x\) 和链底的祖先 \(y\) 。如果 \(x\) 在当前重链上就直接输出,否则 \(u\) 变为 \(y\rightarrow x\) 路径上的下一节点。这一节点显然是 \(y\) 的轻儿子,根据树剖的性质,询问次数不会超过 \(2\times \log n\) 次。
code
#include<cstdio>
inline int gi()
{
char c=getchar(); int x=0;
for(;c<'0'||c>'9';c=getchar());
for(;c>='0'&&c<='9';c=getchar())x=(x<<1)+(x<<3)+c-'0';
return x;
}
const int N=2e5+5;
int head[N],nxt[N<<1],to[N<<1],dep[N],size[N],fa[N],son[N],top[N],bot[N],n;
void addedge(int u, int v, int now) {
nxt[now]=head[u], head[u]=now, to[now]=v;
}
void dfs(int u)
{
size[u]=1;
for(int e=head[u];e;e=nxt[e])
{
if(to[e]==fa[u]) continue;
dep[to[e]]=dep[u]+1;
fa[to[e]]=u;
dfs(to[e]);
size[u]+=size[to[e]];
if(size[to[e]]>size[son[u]]) son[u]=to[e];
}
}
void dfs2(int u, int tp)
{
top[u]=tp;
if(son[u]) dfs2(son[u],tp),bot[u]=bot[son[u]];
else bot[u]=u;
for(int e=head[u];e;e=nxt[e])
if(to[e]!=fa[u]&&to[e]!=son[u]) dfs2(to[e],to[e]);
}
int main()
{
n=gi();
for(int i=1;i<n;++i)
{
int u=gi(),v=gi();
addedge(u,v,i*2-1);
addedge(v,u,i*2);
}
dfs(1),dfs2(1,1);
puts("d 1"),fflush(stdout);
int x=gi(),u=1;
while(true)
{
printf("d %d\n",bot[u]),fflush(stdout);
int dis=gi(),t=x+dep[bot[u]]-dis>>1;
while(dep[u]!=t) u=son[u];
if(t+dis==dep[bot[u]])
{
printf("! %d\n",u),fflush(stdout);
return 0;
}
printf("s %d\n",u),fflush(stdout);
u=gi();
}
}