首页 > 其他分享 >【考后总结】8.18 暑假模拟27

【考后总结】8.18 暑假模拟27

时间:2022-08-18 21:13:26浏览次数:51  
标签:表盘 27 dbinom int siz maxn 8.18 mod 考后

概述

又名:暑假集训6
得分:\(40+20+20+10=90\)
rk 11

赛时

打得比较懵,很多部分分想了很久才打出来。

题解

T1 接力游戏

题意

给序列 \(a,b\),每个序列包含两个属性 \(w,v\),从序列中任意选择元素,求在保证两序列各自选择元素中 \(w\) 之和相等的情况下,最大的 \(v\) 和。

思路

背包问题,想了个优化,发现会增加一个 \(\log\),正解的玄学优化是排序用前缀和卡一下上下界。

代码

点击查看代码
int n,m;
struct node{
    int w,v;
    bool operator<(const node&rhs)const{
        return w<rhs.w;
    }
}a[1005],b[1005];
int suma[1005],sumb[1005];
ll f[maxn],g[maxn];
ll ans;
int main(){
    freopen("game.in","r",stdin);
    freopen("game.out","w",stdout);
    n=read(),m=read();
    for(int i=1;i<=n;++i){
        a[i].w=read(),a[i].v=read();
    }
    for(int i=1;i<=m;++i){
        b[i].w=read(),b[i].v=read();
    }
    sort(a+1,a+n+1);
    sort(b+1,b+m+1);
    for(int i=1;i<=n;++i) suma[i]=suma[i-1]+a[i].w;
    for(int i=1;i<=m;++i) sumb[i]=sumb[i-1]+b[i].w;
    memset(f,-0x3f,sizeof(f));
    memset(g,-0x3f,sizeof(g));
    f[0]=g[0]=0;
    for(int i=1;i<=n;++i){
        for(int j=suma[i];j>=a[i].w;--j){
            if(f[j-a[i].w]==-0x3f3f3f3f3f3f3f3f) continue;
            f[j]=max(f[j],f[j-a[i].w]+a[i].v);
        }
    }
    for(int i=1;i<=m;++i){
        for(int j=sumb[i];j>=b[i].w;--j){
            if(g[j-b[i].w]==-0x3f3f3f3f3f3f3f3f) continue;
            g[j]=max(g[j],g[j-b[i].w]+b[i].v);
        }
    }
    for(int i=1;i<=min(suma[n],sumb[m]);++i){
        ans=max(ans,f[i]+g[i]);
    }
    printf("%lld\n",ans);
    return 0;
}

T2 树上竞技

题意

给定一棵 \(n\) 个节点的树,从中随机选择 \(m\) 个,找到一个节点使的这个节点到所选择的节点的最短路径之和最小,求所有选择方案对应的最小值之和。

思路

赛时推出来这样的节点只有一个,没有突破计算答案来源的瓶颈。
考虑一条边 \(e\),其两端点 \(u,v\) 两侧选择的节点个数 \(i\) 与 \(m-i\),两侧可选择的节点个数 \(siz\) 与 \(n-siz\),那么有:

\[f(e)=\sum_{i=1}^{m-1}\dbinom{siz}{i}\dbinom{n-siz}{m-i}\times \min(i,m-i) \]

大致意思是在保证这条边会被经过的前提下,其贡献就是选取方案以及较小一侧的选取点个数(最优的点一定在较大一侧)。
考虑到这个 \(\min\) 不好处理,设 $k=\left\lfloor\dfrac{m-1}{2}\right\rfloor$,于是换成:

\[2\times \sum_{i=1}^{k} \dbinom{siz}{i}\dbinom{n-siz}{m-i}\times i \]

特别对于 \(2\mid m\) 的情况,还有:

\[\dbinom{siz}{\tfrac{m}{2}}\dbinom{n-siz}{\tfrac{m}{2}}\times \dfrac{m}{2} \]

考虑上面式子怎么优化(先不管系数),可以把 \(i\) 去掉,得到:

\[\sum_{i=1}^{k}\dbinom{siz-1}{i-1}\dbinom{n-siz}{m-i}\times siz \]

设其为 \(siz\times g(siz)\),考虑如何转移。
然后是神秘的组合意义,将其理解成在 \(n-1\) 个元素中,总共选取 \(m-1\) 个,限制在前 \(siz-1\) 位置中至多选取 \(k-1\) 个,那么当且仅当目前依然在前 \(siz-1\) 位置中选取 \(k-1\) 个,又在 \(siz\) 位置选取了 \(1\) 个,\(g(siz)\) 对于 \(g(siz+1)\) 是不合法的,这个不合法的方案数就是:

\[\dbinom{siz-1}{k-1}\dbinom{n-1-siz}{m-1-(k-1)-1} \]

于是就可以递推了。

代码

点击查看代码
int n,m;
vector<int> E[maxn];
inline int q_pow(int x,int p){
    int res=1;
    while(p){
        if(p&1) res=1ll*res*x%mod;
        x=1ll*x*x%mod;
        p>>=1;
    }
    return res;
}
int fac[maxn],inv[maxn];
inline int C(int N,int M){
    return 1ll*fac[N]*inv[M]%mod*inv[N-M]%mod;
}
int g[maxn];
int siz[maxn];
ll ans;
void dfs(int u,int f){
    siz[u]=1;
    for(int v:E[u]){
        if(v==f) continue;
        dfs(v,u);
        siz[u]+=siz[v];
    }
    ans=(ans+g[siz[u]]+g[n-siz[u]])%mod;
    if(m%2==0) ans=(ans+1ll*C(siz[u],m/2)*C(n-siz[u],m/2)%mod*m/2%mod)%mod;
}
int main(){
    freopen("meeting.in","r",stdin);
    freopen("meeting.out","w",stdout);
    n=read(),m=read();
    for(int v=2;v<=n;++v){
        int u=read();
        E[u].push_back(v);
        E[v].push_back(u);
    }
    fac[0]=inv[0]=1;
    for(int i=1;i<=n;++i) fac[i]=1ll*fac[i-1]*i%mod;
    inv[n]=q_pow(fac[n],mod-2);
    for(int i=n-1;i>=1;--i) inv[i]=1ll*inv[i+1]*(i+1)%mod;
    int k=(m-1)/2;
    if(k>=1) g[1]=C(n-1,m-1);
    for(int i=1;i<n;++i) g[i+1]=(g[i]-1ll*C(i-1,k-1)*C(n-1-i,m-1-(k-1)-1)%mod+mod)%mod;
    for(int i=1;i<=n;++i) g[i]=1ll*g[i]*i%mod;
    dfs(1,0);
    printf("%lld\n",ans);
    return 0;
}

T3 虚构推理

题意

给定 \(n\) 个表盘,求出一个表盘使得其与这些表盘的时针夹角或分针夹角的最大值最小,求出这个最小值。

思路

可以暴力。
先求出每个表盘的分针与时针度数,排序后枚举表盘(这里秒要枚举到小数,不然精度不够,考场上一直卡在这里),二分可以找到与当前表盘时针/分针夹角最大的两个表盘,其夹角的最大值就是当前表盘的答案。

代码

点击查看代码
int n;
char ch[10];
db degh[maxn],degm[maxn];
inline db get_deg(db d1,db d2){
    return min(fabs(d1-d2),360.0-fabs(d1-d2));
}
inline db chk_h(db dh){
    int lpos,rpos;
    if(dh<=180.0) rpos=lower_bound(degh+1,degh+n+1,dh+180.0)-degh,lpos=rpos-1;
    else rpos=lower_bound(degh+1,degh+n+1,dh-180.0)-degh,lpos=rpos-1;
    if(rpos>n) rpos=1;
    if(lpos<1) lpos=n;
    return max(get_deg(dh,degh[lpos]),get_deg(dh,degh[rpos]));
}
inline db chk_m(db dm){
    int lpos,rpos;
    if(dm<=180.0) rpos=lower_bound(degm+1,degm+n+1,dm+180.0)-degm,lpos=rpos-1;
    else rpos=lower_bound(degm+1,degm+n+1,dm-180.0)-degm,lpos=rpos-1;
    if(rpos>n) rpos=1;
    if(lpos<1) lpos=n;
    return max(get_deg(dm,degm[lpos]),get_deg(dm,degm[rpos]));
}
db ans=1000.0;
int main(){
    freopen("unreal.in","r",stdin);
    freopen("unreal.out","w",stdout);
    n=read();
    for(int i=1;i<=n;++i){
        scanf("%s",ch+1);
        int h=(ch[1]-'0')*10+(ch[2]-'0'),m=(ch[4]-'0')*10+(ch[5]-'0'),s=(ch[7]-'0')*10+(ch[8]-'0');
        //printf("%d %d %d\n",h,m,s);
        degh[i]=1.0*((h%12)*3600+m*60+s)/43200*360,degm[i]=1.0*(m*60+s)/3600*360;
    }
    sort(degh+1,degh+n+1);
    sort(degm+1,degm+n+1);
    degh[0]=degh[n+1]=-1.0,degm[0]=degm[n+1]=-1.0;
    for(int h=0;h<12;++h){
        for(int m=0;m<60;++m){
            for(db s=0;s<60;s+=0.1){
                db dh=1.0*(h*3600+m*60+s)/43200*360,dm=1.0*(m*60+s)/3600*360;
                ans=min(ans,max(chk_h(dh),chk_m(dm)));
            }
        }
    }
    printf("%.5lf\n",ans);
    return 0;
}

T4 记忆碎片

题意

给一个 \(n\) 个点的完全图以及最小生成树的边权,求出满足这样的完全图个数。

思路

好厉害的题。
首先对 \(n\) 做整数拆分,拆成若干个联通块,两两合并。
枚举每一条边,若是树边则合并两个联通块,反之则在其中随意连边,这个过程可以用 \(\text{dp}\) 实现,具体是 设 \(dp(i,j)\) 表示前 \(i\) 条边在第 \(j\) 个拆分方案中的方案数。
一些优化(可以但没有也行):

  • 非树边可以用下降幂优化去掉一个 \(n\)。
  • 使用 \(\text{bfs}\) 预处理拆分可以连边,然后在图上转移
  • 使用 bitset

代码

点击查看代码
int n;
int tot;
vector<int> S[40005],tmp;
map<vector<int>,int> mp;
int cnt_edge[40005];
bool mark[1605];
void dfs(int l,int r){
    if(!r){
        S[++tot]=tmp;
        mp[S[tot]]=tot;
        for(int i:S[tot]){
            cnt_edge[tot]+=i*(i-1)/2;
        }
        return;
    }
    if(l>r) return;
    for(int i=l;i<=r;++i){
        tmp.push_back(i);
        dfs(i,r-i);
        tmp.pop_back();
    }
}
ll dp[1605][40005];
int main(){
    freopen("tree.in","r",stdin);
    freopen("tree.out","w",stdout);
    n=read();
    for(int i=1;i<n;++i) mark[read()]=1;
    dfs(1,n);
    dp[0][1]=1;
    for(int i=1;i<=n*(n-1)/2;++i){
        for(int j=1;j<=tot;++j){
            if(!dp[i-1][j]) continue;
            if(mark[i]){
                //树边合并
                for(int x=0;x<S[j].size();++x){
                    for(int y=x+1;y<S[j].size();++y){
                        tmp.clear();
                        tmp.push_back(S[j][x]+S[j][y]);
                        for(int z=0;z<S[j].size();++z){
                            if(z!=x&&z!=y) tmp.push_back(S[j][z]);
                        }
                        sort(tmp.begin(),tmp.end());
                        int nxt=mp[tmp];
                        dp[i][nxt]=(dp[i][nxt]+dp[i-1][j]*S[j][x]%mod*S[j][y]%mod)%mod;
                    }
                }
            }
            else{
                //非树边随便连一条
                dp[i][j]=(dp[i][j]+dp[i-1][j]*(cnt_edge[j]-(i-1))%mod)%mod;
            }
        }
    }
    printf("%lld\n",dp[n*(n-1)/2][tot]);
    return 0;
}

标签:表盘,27,dbinom,int,siz,maxn,8.18,mod,考后
From: https://www.cnblogs.com/SoyTony/p/16600114.html

相关文章

  • 8.18
    下发文件和题解T1接力比赛既然要求取小白与小黑班级总值相等时总的最大值,那么这就可以转化为最简单的背包问题.设和分别表示小黑和小白班级中值为时的......
  • 8.18总结
    泡泡堂\(solution\)苹果树\(solution\)字符合并\(solution\)脑洞治疗仪\(solution\)万万没想到,我50pts的原因是数组没开够线段树维护修改操作,注意先挖后补ACCo......
  • 8.18集训
    回到了Luogu,继续刷COCI……上午事实证明后三题是可做题,前三题不大可做。T1P6405开始码了一个相邻的树木连边,边权设为相等的时间,然后点边互换跑连通块算大小,默认恒等......
  • NOIP2022模拟赛一 By RSJ 08.18
    A.「NOIP2022模拟赛一ByRSJ」StringSearchPro给定一个\(01\)字符串,查找一个子串使得\(0\)在这个子串中出现了\(\frac{p}{q}\cdotk\)次,其中\(k\)是子串长度\(n,p,q......
  • 27、绑定方法与非绑定方法
    27、绑定方法与非绑定方法  目录:绑定方法与非绑定方法非绑定方法视频链接 一绑定方法与非绑定方法​类中定义的函数分为两大类:绑定方法和非绑......
  • 《GB27701-2011》PDF下载
    《GB27701-2011阴极射线管机械安全》PDF下载《GB27701-2011》简介本标准适用于作为电器装置的部件并且采用整体防爆方式的阴极射线管和阴极射线管组件;这些要求适用于在......
  • 《GB27995.2-2011》PDF下载
    《GB27995.2-2011半成品眼镜片毛坯第2部分:渐变焦眼镜片毛坯规范》PDF下载《GB27995.2-2011》简介GB27995的本部分规定了渐变焦半成品眼镜片毛坯的光学和几何性能的要......
  • 《GB27695-2011》PDF下载
    《GB27695-2011汽车举升机安全规程》PDF下载《GB27695-2011》简介本标准规定了汽车举升机的设计、制造、安装、使用、维护、报废和检查等方面的基本安全要求;本标准适......
  • 《GB27742-2011》PDF下载
    《GB27742-2011可免于辐射防护监管的物料中放射性核素活度浓度》PDF下载《GB27742-2011》简介本标准规定了可免于辐射防护监管的物料中放射性核素活度浓度。本标准适......
  • Bzoj 2724 [Violet 6]蒲公英
    原题链接https://darkbzoj.cc/problem/2724大致题意:给一个长度为n的序列,进行m次询问,每次询问输出区间内出现次数最多的数,强制在线。离散化加分块对于离散化后的每个数......