E.F(cf div2 Round 66)

E.Ehab and the Expected GCD Problem

题意:对n的一个排列,使这个排列中前缀的不同gcd个数最大,问有多少种这样的排列?

思路:考虑gcd的衰减,所以第一个数一定有最多的质因子个数。那么它一定是形如2^x*3^y,(其中y<=1)。因为任何比3大的质数都至少可以提供2个2,而3^2可以提供3个2。

所以我们可以考虑如下的dp:

dp[i][j][k],i是枚举到的下标,j是gcd中2个数,k是gcd中3个数。

dp[i+1][x][y]=dp[i+1][x][y]+dp[i][x][y]∗(f(x,y)−i)

dp[i+1][x−1][y]=dp[i+1][x−1][y]+dp[i][x][y]∗(f(x−1,y)−f(x,y))

dp[i+1][x][y−1]=dp[i+1][x][y−1]+dp[i][x][y]∗(f(x,y−1)−f(x,y))dp[i+1][x][y−1]=dp[i+1][x][y−1]+dp[i][x][y]∗(f(x,y−1)−f(x,y))

f(x,y)是n中至少含x个2,y个3的数的数量。

#include <bits/stdc++.h>

using namespace std;
#define N 1000005
#define ll long long
#define mod 1000000007
#define inf 0x3f3f3f3f
#define go(i,a,b) for(int i=(a);i<=(b);i++)
#define dep(i,a,b) for(int i=(a);i>=(b);i++)
#define add(a,b) a=((b)+a)%mod
int f[50][2],dp[N][22][3];
int n,m;
int r0(int x){return !x?0:r0(x/2)+1; }
int main()
{
    cin>>n;
    m=r0(n)-1;
    go(i,0,m)f[i][0]=n/(1<<i),f[i][1]=n/(1<<i)/3;
    dp[1][m][0]=f[m][0];
    dp[1][m-1][1]=f[m-1][1];
    go(i,2,n){
        go(j,0,m)
            go(k,0,1)
                add(dp[i][j][k],1ll*dp[i-1][j][k]*max((f[j][k]-i+1),0)%mod),
                add(dp[i][j][k],1ll*dp[i-1][j+1][k]*(f[j][k]-f[j+1][k])%mod),
                add(dp[i][j][k],1ll*dp[i-1][j][k+1]*(f[j][k]-f[j][k+1])%mod);
    }
    cout<<dp[n][0][0]<<endl;
    return 0;
}

 

F.Ehab and the Big Finale

题意:交互。给以一颗根节点为1的树,让你找一个被选定的点x。两种操作:询问u到x的距离,询问u到x路径上的第二个点(u必须是x的祖先)。

思路:做的时候想了sqrt(n)的思路,后来去看了题解。

首先划分轻重链。首先开始的时候根节点是1,然后询问根节点重链上最后一个结点u与x的距离,判一下如果x在链上,那么x是u的lca,否则找到lca,让lca到x路径上的第二个点成为新的根。,这个点是轻儿子,这样新的树的大小一定小于原树的1/2。

#include <bits/stdc++.h>

using namespace std;
#define N 200005
#define ll long long
#define mod 1000000007
#define inf 0x3f3f3f3f
#define go(i,a,b) for(int i=(a);i<=(b);i++)
#define dep(i,a,b) for(int i=(a);i>=(b);i++)
int dep[N],deep[N],fa[N],num[N],son[N],tot,n;
int pri(int x,int f){
    if(f==1)printf("d %d\n",x);
    if(f==2)printf("s %d\n",x);
    if(f==3)printf("! %d\n",x);
    fflush(stdout);
    int res;
    if(f<3)scanf("%d",&res);
    return res;
}
vector<int>path[N];
void  dfs(int u,int fath,int dep){
    deep[u]=dep;
    fa[u]=fath;
    num[u]=1;
    for(auto v:path[u]){
        if(v==fath)continue;
        dfs(v,u,dep+1);
        num[u]+=num[v];
        if(num[v]>num[son[u]] ) son[u]=v;
    }
}
int gettool(int x){

    return x;
}
int u,to;
int main()
{
    cin>>n;
    go(i,2,n)scanf("%d %d",&u,&to),path[u].push_back(to),path[to].push_back(u);
    dfs(1,0,0);
    int dep=pri(1,1),x=1;
    while(deep[x]!=dep){
        while(son[x])x=son[x];
        int k=pri(x,1);
        if(k==deep[x]-dep)while(k--)x=fa[x];
        else {
            k=(k+deep[x]-dep)/2;
            while(k--)x=fa[x];
            x=pri(x,2);
        }
    }
    pri(x,3);
    return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章