2020牛客多校第五场By Rynar

A.Portal

B.Graph

思路:观察分析得,所求值为异或最小生成树的边权和,利用字典树,把每个数按其bit插入深度为30的字典树中,O(nlogn)

const int N=2e5+10;
const int inf=0x3f3f3f3f;
int n;
vector<pair<int,int> >v[N];
int l[N*40],r[N*40],nx[N*40][2];
ll exor[N];
int root,tot;
void dfs(int x,int fa){
    for (pair<int,int> i:v[x]){
        if (i.first==fa)continue;
        exor[i.first]=exor[x]^i.second;
        dfs(i.first,x);
    }
}
void insert(int &now,int id,int dep){//插入第id大的数,这个数的bit位为字典树的节点
    if(!now)now=++tot;
    l[now]=min(l[now],id),r[now]=max(r[now],id);
    if(dep<0)return;
    ll bit=(exor[id]>>dep)&1;
    insert(nx[now][bit],id,dep-1);
}
ll query(int now,ll val,int dep){
    if(dep<0)return 0;
    ll bit=(val>>dep)&1;
    if(nx[now][bit]) return query(nx[now][bit],val,dep-1);
    else return query(nx[now][bit^1],val,dep-1)+(1<<dep);//异或为1,加上该深度权值,因为存在左右2数,必定能往下搜
}
ll solve(int now,int dep){
    int ls=nx[now][0],rs=nx[now][1];
    if (dep<0)return 0;
    if (r[ls]&&r[rs]){//存在左右的2数
        ll mi=inf;
        for (int i=l[ls];i<=r[ls];i++)mi=min(mi,query(rs,exor[i],dep-1));//找出左右异或最小的值,且必须要加上这个值,因为没有其他的异或值比这个更小
        return solve(ls,dep-1)+solve(rs,dep-1)+mi+(1<<dep);
    }
    if (r[ls])return solve(ls,dep-1);
    if (r[rs])return solve(rs,dep-1);
    return 0;
}
int main(){
    int x,y,z;
    scanf("%d",&n);
    for (int i=1;i<n;i++){
        scanf("%d%d%d",&x,&y,&z);
        x++;y++;
        v[x].push_back({y,z});v[y].push_back({x,z});
    }
    exor[0]=0;dfs(1,0);
    sort(exor+1,exor+1+n);
    memset(l,inf,sizeof l);
    for (int i=1;i<=n;i++)insert(root,i,30);
    cout<<solve(root,30)<<endl;
    return 0;
}

C.Easy

思路:
,建立此生成函数,满足|x|,|y|<1,列出每项,通过等差数列的性质得出右边公式

取其中的x^n*y^m就能得到答案
而(1+x+x^2+...)^k,取其中的x^t,系数为(k-1+t)C(k-1)

const int mod=998244353;
const int N=1e6+10;
ll inv[N],f[N];
void get_inv(int n,int p){
    inv[0]=inv[1]=1;
    for (int i=2;i<=n;i++)inv[i]=inv[p%i]*(p-p/i)%p;
}
ll C(int x,int y){
    return f[x]*inv[x-y]%mod*inv[y]%mod;
}
int main(){
    int T,n,m,k;
    get_inv(N-1,mod);
    for (int i=1;i<N;i++)inv[i]=inv[i]*inv[i-1]%mod;
    f[0]=1;
    for (int i=1;i<N;i++)f[i]=f[i-1]*i%mod;
    cin>>T;
    while (T--){
        scanf("%d%d%d",&n,&m,&k);
        ll ans=0;
        for (int i=0;i<=min(n,m)-k;i++){
            ans=(ans+C(k+i-1,k-1)*C(n-i-1,k-1)%mod*C(m-i-1,k-1)%mod)%mod;//xy个数x个数y个数
        }
        printf("%lld\n",ans);
    }
}

D.Drop Voicing

思路:不管是顺时针逆时针旋转,可以保证一个序列的单调性不变,只需保证最长上升子序列的单调性不变,其他元素每个都需要1次操作

const int N=500+10;
int a[N],f[N];
int main(){
    int n;
    scanf("%d",&n);
    for (int i=1;i<=n;i++)scanf("%d",&a[i]);
    int mx=0;
    for (int k=1;k<=n;k++){
        int t=a[1];
        for (int j=2;j<=n;j++)a[j-1]=a[j];
        a[n]=t;
        int len=0;
        for(int i=0;i<n;i++){//最长上升子序列
            int x=a[i+1];
            if(len==0)f[len++]=x;
            else if(x>f[len-1])f[len++]=x;
            else{
                int k=lower_bound(f,f+len,x)-f;
                f[k]=x;
            }
        }
        mx=max(len,mx);
    }
    cout<<n-mx<<endl;
    return 0;
}

E.Bogo Sort

n=int(input())
arr=input()
arr="0 "+arr
a=[int(i) for i in arr.split()]
def gcd(x,y):
    if y:
        return gcd(y,x%y)
    else:
        return x
def lcm(x,y):
    return x*y//gcd(x,y)
ans=1
vis=[0]*200000
for i in range(1,n+1):
    if vis[i]:
        continue
    p=i
    cnt=1
    vis[p]=1
    while vis[a[p]]==0:
        p=a[p]
        vis[p]=1
        cnt+=1
    ans=lcm(ans,cnt)
print(ans)

F.DPS

const int N=100+10;
int a[N];
int main(){
    int n;
    cin>>n;
    int mx=0;
    for (int i=1;i<=n;i++)scanf("%d",&a[i]),mx=max(mx,a[i]);
    for (int i=1;i<=n;i++){
        ll t=1ll*50*a[i]/mx;if (1ll*50*a[i]%mx)t++;
        printf("+");
        for (int i=1;i<=t;i++)printf("-");
        printf("+\n");
        printf("|");
        for (int i=1;i<t;i++)printf(" ");
        if (a[i]==mx)printf("*");
        else if (a[i]!=0)printf(" ");
        printf("|%d\n",a[i]);
        printf("+");
        for (int i=1;i<=t;i++)printf("-");
        printf("+\n");
    }
    return 0;
}

G.Greetings Souvenir

H.Interval

I.Hard Math Problem

/*
GHHGHHGHHGHH
HHEHHEHHEHHE
HGHHGHHGHHGH
EHHEHHEHHEHH
*/
int main(){
    cout<<"0.666667"<<endl;
}

J.Cone walker

K.Git Merge

posted @ 2020-07-25 18:20  Rynar  阅读(496)  评论(0)    收藏  举报