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();
}
}