网太卡只好做划水选手,只做EF。
E
很容易发现第一个数是2k或者是3*2k-1,因为消去因子次数要尽可能多,然后可以直接dp一发转移还剩几个2/3即可,写起来有些麻烦

#include<bits/stdc++.h> using namespace std; const int N=1e6+7,mod=1e9+7; int n,k,ans,a[21][2],f[N][21][2]; int count(int x) { int ret=0; while(x%2==0)ret++,x/=2; return ret; } int main() { scanf("%d",&n); if(n<=2){puts("1");return 0;} for(int i=20;i;i--)if((1<<i)<=n){k=i;break;} for(int i=1;i<=n;i++)a[count(i)][0]++; for(int i=k-1;~i;i--)a[i][0]+=a[i+1][0]; f[1][k][0]=1; for(int i=2;i<=n;i++) for(int j=0;j<=k;j++) { f[i][j][0]=(f[i][j][0]+1ll*f[i-1][j+1][0]*(a[j][0]-a[j+1][0]))%mod; f[i][j][0]=(f[i][j][0]+1ll*f[i-1][j][0]*(a[j][0]-i+1))%mod; } ans=f[n][0][0]; if((1<<k-1)*3<=n) { memset(f,0,sizeof f); memset(a,0,sizeof a); for(int i=1;i<=n;i++)a[count(i)][i%3==0]++; for(int i=k-1;~i;i--)a[i][0]+=a[i+1][0],a[i][1]+=a[i+1][1]; f[1][k-1][1]=1; for(int i=2;i<=n;i++) for(int j=0;j<k;j++) { f[i][j][1]=(f[i][j][1]+1ll*f[i-1][j+1][1]*(a[j][1]-a[j+1][1]))%mod; f[i][j][1]=(f[i][j][1]+1ll*f[i-1][j][1]*(a[j][1]-i+1))%mod; f[i][j][0]=(f[i][j][0]+1ll*f[i-1][j+1][0]*(a[j][0]+a[j][1]-a[j+1][0]-a[j+1][1]))%mod; f[i][j][0]=(f[i][j][0]+1ll*f[i-1][j][0]*(a[j][0]+a[j][1]-i+1))%mod; f[i][j][0]=(f[i][j][0]+1ll*f[i-1][j][1]*a[j][0])%mod; } ans=(ans+f[n][0][0])%mod; } printf("%d",ans); }
F
可以考虑树剖,然后询问时,若询问的lca不在重儿子上,则大小/2,反之下logn次即可,容易证明这个询问次数是log级别的

#include<bits/stdc++.h> using namespace std; const int N=2e5+7; int n,dis,dep[N],sz[N],son[N],ed[N]; vector<int>G[N]; void dfs(int u,int fa) { sz[u]=1; for(int i=0;i<G[u].size();i++) if(G[u][i]!=fa) { dep[G[u][i]]=dep[u]+1,dfs(G[u][i],u),sz[u]+=sz[G[u][i]]; if(sz[G[u][i]]>sz[son[u]])son[u]=G[u][i]; } ed[u]=son[u]?ed[son[u]]:u; } int askd(int x) { printf("d %d ",x),fflush(stdout); scanf("%d",&x); return x; } int asks(int x) { printf("s %d ",x),fflush(stdout); scanf("%d",&x); return x; } int solve(int u) { if(dep[u]==dis)return u; if(dis-dep[u]==1)return asks(u); int lca=dep[ed[u]]+dis-askd(ed[u])>>1; if(dep[u]==lca)return solve(asks(u)); while(dep[u]!=lca&&dep[u]!=dis)u=son[u]; return solve(u); } int main() { scanf("%d",&n); for(int i=1,x,y;i<n;i++)scanf("%d%d",&x,&y),G[x].push_back(y),G[y].push_back(x); dfs(1,0),dis=askd(1); printf("! %d",solve(1)); }