Codeforces Round #563 (Div. 2) 划水记

网太卡只好做划水选手,只做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);
}
View Code

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));
}
View Code
原文地址:https://www.cnblogs.com/hfctf0210/p/10977909.html