2020.12.16 模拟赛x+1
A. 接力比赛
跑两遍背包,再进行一些玄学的剪枝
代码
#include<cstdio>
#include<algorithm>
#define rg register
inline int read(){
rg int x=0,fh=1;
rg char ch=getchar();
while(ch<'0' || ch>'9'){
if(ch=='-') fh=-1;
ch=getchar();
}
while(ch>='0' && ch<='9'){
x=(x<<1)+(x<<3)+(ch^48);
ch=getchar();
}
return x*fh;
}
const int maxn=1e3+5,maxm=1e6+5;
int n,m,maxa,maxb,mmax;
long long fa[maxm],fb[maxm],ans=0;
struct asd{
int val,cost;
}b1[maxn],b2[maxn];
bool cmp(asd aa,asd bb){
return aa.val>bb.val;
}
int main(){
n=read(),m=read();
for(rg int i=1;i<=n;i++){
b1[i].cost=read(),b1[i].val=read();
}
for(rg int i=1;i<=m;i++){
b2[i].cost=read(),b2[i].val=read();
}
mmax=700;
std::sort(b1+1,b1+1+n,cmp);
std::sort(b2+1,b2+1+m,cmp);
for(rg int i=1;i<=mmax;i++){
maxa+=b1[i].cost;
}
for(rg int i=1;i<=mmax;i++){
maxb+=b2[i].cost;
}
for(rg int i=1;i<=maxa;i++){
fa[i]=-0x3f3f3f3f3f3f3f3f;
}
for(rg int i=1;i<=maxb;i++){
fb[i]=-0x3f3f3f3f3f3f3f3f;
}
for(rg int i=1;i<=mmax;i++){
for(rg int j=maxa;j>=b1[i].cost;j--){
fa[j]=std::max(fa[j],fa[j-b1[i].cost]+b1[i].val);
}
}
for(rg int i=1;i<=mmax;i++){
for(rg int j=maxb;j>=b2[i].cost;j--){
fb[j]=std::max(fb[j],fb[j-b2[i].cost]+b2[i].val);
}
}
for(rg int i=1;i<=maxa;i++){
ans=std::max(ans,fa[i]+fb[i]);
}
printf("%lld\n",ans);
return 0;
}
B. 树上竞技
单独考虑每一条边的贡献
设该边一侧关键点的个数为 \(x\) ,则另一侧关键点的个数为 \(m-x\)
那么最终的集合点一定会选在点比较多的那一侧,因为我们要让尽量少的点经过这条边
设该边一侧点的个数为 \(s\) ,则另一侧点的个数为 \(n-s\)
该边的答案就是 \(\sum_{i=1}^{m-1}C_s^i \times C_{n-s}^{m-i} \times min(i,m-i)\)
带着 \(min\) 不好处理,我们把它展开
_{S}^{\frac{m}{2}} \times C_{n-S}^{\frac{m}{2}} \times \frac{m}{2}\]
前两项本质是相同的,最后一项加的时候特判一下即可
变一下形式\(\sum_{i=1}^{\frac{m-1}{2}} C_{S}^{i} C_{n-S}^{m-i} \times i=\sum_{i=1}^{\frac{m-1}{2}} C_{S-1}^{i-1} C_{n-S}^{m-i} \times s\)
令 \(k=\frac{m-1}{2}\)
则 \(G(S) = \sum_{i=1}^{k} C_{S-1}^{i-1} C_{n-S}^{m-i}\)
所以我们只需要求出 \(G(s)\) 即可
我们现在考虑 \(G(s)\) 的组合意义,可以理解为 \(n-1\) 个物品里一共要选 \(m-1\) 个,前面 \(s-1\) 个里最多选 \(k-1\) 个的方案数
要从 \(G(i)\) 变成 \(G(i+1)\),发现答案变少的部分就是前面 \(i-1\) 个选了 \(k-1\) 个,而 \(i\) 也被选中了
只有这种情况会被 \(G(i)\) 计算而不会被 \(G(i+1)\) 计算
\(O(n)\) 递推即可计算,最后枚举每一条边算贡献再累加即可
代码
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#define rg register
inline int read(){
rg int x=0,fh=1;
rg char ch=getchar();
while(ch<'0' || ch>'9'){
if(ch=='-') fh=-1;
ch=getchar();
}
while(ch>='0' && ch<='9'){
x=(x<<1)+(x<<3)+(ch^48);
ch=getchar();
}
return x*fh;
}
const int mod=1e9+7,maxn=1e6+5;
int h[maxn],tot=1,n,m;
struct asd{
int to,nxt;
}b[maxn<<1];
void ad(rg int aa,rg int bb){
b[tot].to=bb;
b[tot].nxt=h[aa];
h[aa]=tot++;
}
int siz[maxn],ans;
void dfs(rg int now,rg int lat){
siz[now]=1;
for(rg int i=h[now];i!=-1;i=b[i].nxt){
rg int u=b[i].to;
if(u==lat) continue;
dfs(u,now);
siz[now]+=siz[u];
}
}
int ny[maxn],jc[maxn],jcc[maxn],fa[maxn];
int getC(rg int nn,rg int mm){
return 1LL*jc[nn]*jcc[mm]%mod*jcc[nn-mm]%mod;
}
void pre(){
ny[1]=1;
for(rg int i=2;i<maxn;i++){
ny[i]=1LL*(mod-mod/i)*ny[mod%i]%mod;
}
jc[0]=jcc[0]=1;
for(rg int i=1;i<maxn;i++){
jc[i]=1LL*jc[i-1]*i%mod;
jcc[i]=1LL*jcc[i-1]*ny[i]%mod;
}
}
int anss[maxn];
int js(rg int aa,rg int bb){
if(aa>bb) std::swap(aa,bb);
if(anss[aa]!=-1) return anss[aa];
rg int nans=0;
for(rg int i=1;i<=m-1;i++){
rg int j=m-i;
if(aa<i) break;
if(bb<j) continue;
nans+=1LL*getC(aa,i)*getC(bb,j)%mod*std::min(i,j)%mod;
if(nans>=mod) nans-=mod;
}
return anss[aa]=nans;
}
void dfs2(rg int now,rg int lat){
for(rg int i=h[now];i!=-1;i=b[i].nxt){
rg int u=b[i].to;
if(u==lat) continue;
ans+=js(siz[u],n-siz[u]);
if(ans>=mod) ans-=mod;
dfs2(u,now);
}
}
int getsum(int num){
return 1LL*num*(num+1)/2LL%mod;
}
bool haha=1;
int main(){
memset(h,-1,sizeof(h));
memset(anss,-1,sizeof(anss));
n=read(),m=read();
for(rg int i=2;i<=n;i++){
fa[i]=read();
if(fa[i]!=i-1) haha=0;
ad(fa[i],i);
ad(i,fa[i]);
}
pre();
if(n<1000000 && m>=200000) {
rg int cs;
if(m!=1){
pre();
for(rg int i=1;i<=n;i++){
if(i-1<m/2 || n-i<m/2) continue;
cs=1LL*getC(i-1,m/2)*getC(n-i,m/2)%mod;
ans+=1LL*cs*(m/2)%mod*getsum(i-1)%mod*ny[i-1]%mod;
if(ans>=mod) ans-=mod;
ans+=1LL*cs*(m/2)%mod*getsum(n-i)%mod*ny[n-i]%mod;
if(ans>=mod) ans-=mod;
}
}
} else {
dfs(1,0);
dfs2(1,0);
}
printf("%d\n",ans);
return 0;
}
C. 虚构推理
可以枚举每一个时刻,然后取最小值
但是秒不一定是整数,所以直接枚举精度不大好处理
于是可以模拟退火
把时针和分针提前排好序可以做到 \(log(n)\) 计算答案,可以多做不少遍模拟退火
代码比较玄学,多交几遍可以 \(AC\)
代码
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<ctime>
#define rg register
const int maxn=5e4+5;
typedef double db;
const db eps=1e-6,xs=0.999;
struct asd{
int a,b,c;
}jl[maxn];
struct jie{
db jd;
int id;
}orza[maxn],orzb[maxn];
bool cmp(jie aa,jie bb){
return aa.jd<bb.jd;
}
int n,jla,jlb;
db jlc,ans=1000;
db jsfz(rg db a1,rg db b1,rg db c1,rg db a2,rg db b2,rg db c2){
rg db ans1=(db)b1*6.0+(db)c1/10.0;
rg db ans2=(db)b2*6.0+(db)c2/10.0;
return fabs(ans1-ans2);
}
db jssz(rg db a1,rg db b1,rg db c1,rg db a2,rg db b2,rg db c2){
rg db ans1=a1*30+(db)b1/2.0+(db)c1/120.0;
rg db ans2=a2*30+(db)b2/2.0+(db)c2/120.0;
return fabs(ans1-ans2);
}
int ef1(db aa){
rg int l=1,r=n,mids;
if(aa>=360) aa-=360;
if(aa<0) aa+=360;
while(l<=r){
mids=(l+r)>>1;
if(orza[mids].jd>=aa) r=mids-1;
else l=mids+1;
}
return l;
}
int ef2(db aa){
rg int l=1,r=n,mids;
if(aa>=360) aa-=360;
if(aa<0) aa+=360;
while(l<=r){
mids=(l+r)>>1;
if(orzb[mids].jd>=aa) r=mids-1;
else l=mids+1;
}
return l;
}
db jsa(rg int now,rg db aa,rg db bb,rg db cc){
rg int id;
if(now<1 || now>n) return 0;
rg db ans1,ans2;
id=orza[now].id;
ans1=jsfz(aa,bb,cc,jl[id].a,jl[id].b,jl[id].c);
ans2=jssz(aa,bb,cc,jl[id].a,jl[id].b,jl[id].c);
ans1=std::min(ans1,360.0-ans1);
ans2=std::min(ans2,360.0-ans2);
return std::max(ans1,ans2);
}
db jsb(rg int now,rg db aa,rg db bb,rg db cc){
rg int id;
if(now<1 || now>n) return 0;
rg db ans1,ans2;
id=orzb[now].id;
ans1=jsfz(aa,bb,cc,jl[id].a,jl[id].b,jl[id].c);
ans2=jssz(aa,bb,cc,jl[id].a,jl[id].b,jl[id].c);
ans1=std::min(ans1,360.0-ans1);
ans2=std::min(ans2,360.0-ans2);
return std::max(ans1,ans2);
}
db js(rg db aa,rg db bb,rg db cc){
rg db nans=0,jd1=jssz(aa,bb,cc,0,0,0),jd2=jsfz(aa,bb,cc,0,0,0);
rg int wz=ef1(jd1+180.0);
nans=std::max(nans,jsa(wz-1,aa,bb,cc));
nans=std::max(nans,jsa(wz,aa,bb,cc));
nans=std::max(nans,jsa(1,aa,bb,cc));
nans=std::max(nans,jsa(n,aa,bb,cc));
wz=ef2(jd2+180.0);
nans=std::max(nans,jsb(wz-1,aa,bb,cc));
nans=std::max(nans,jsb(wz,aa,bb,cc));
nans=std::max(nans,jsb(1,aa,bb,cc));
nans=std::max(nans,jsb(n,aa,bb,cc));
return nans;
}
void mnth(){
db t=1.0;
rg int aa=12,bb=60;
while(t>eps){
if(aa) aa--;
if(bb) bb--;
rg int na=(jla+aa*(rand()%2-1))%12;
rg int nb=(jlb+bb*(rand()%2-1))%60;
db nc=jlc+(rand()*2-RAND_MAX)%60*t;
if(na<0) na+=12;
if(nb<0) nb+=60;
if(nc<0) nc+=60;
if(nc>=60) nc-=60;
db nw=js(na,nb,nc);
db cha=nw-ans;
if(cha<0){
jla=na,jlb=nb,jlc=nc,ans=nw;
} else if(exp(-cha/t)*RAND_MAX>rand()){
jla=na,jlb=nb,jlc=nc;
}
t*=xs;
}
}
int main(){
srand(time(0));
scanf("%d",&n);
rg char ch1,ch2;
for(rg int i=1;i<=n;i++){
scanf("%02d%c%02d%c%02d",&jl[i].a,&ch1,&jl[i].b,&ch2,&jl[i].c);
jl[i].a%=12;
orza[i].id=orzb[i].id=i;
orza[i].jd=jssz(jl[i].a,jl[i].b,jl[i].c,0,0,0);
orzb[i].jd=jsfz(jl[i].a,jl[i].b,jl[i].c,0,0,0);
}
std::sort(orza+1,orza+1+n,cmp);
std::sort(orzb+1,orzb+1+n,cmp);
ans=js(jla,jlb,jlc);
for(rg int i=1;i<=350;i++){
mnth();
}
printf("%.8f\n",ans);
return 0;
}
D. 记忆碎片
考虑 \(DP\)
设 \(f[i][s]\) 表示当前考虑了前 \(i\) 短的边,联通状态为 \(s\) 的方案数,\(s\) 的表示方法可以使用最小表示法(其实就是\(sort\)之后拿\(vector\)存一下再用 \(map\) 映射)
状态数不是很多,最多只有 \(37338\)
转移时只需要分两种情况
1、当前的边不是最小生成树中的边,此时只能从某一个联通块中选两个没有边的点去连
2、当前的边是最小生成树中的边,考虑当前边连接了哪两个之前没有相连的联通块即可
常数巨大
代码
#include<cstdio>
#include<algorithm>
#include<vector>
#include<map>
#define rg register
const int maxn=45,maxm=40005,mod=1e9+7;
int n,f[maxn*maxn][maxm],tot,sum[maxm],m;
bool vis[maxn*maxn];
std::vector<int> g[maxm],cs;
std::map<std::vector<int>,int> mp;
void dfs(rg int now,rg int lat){
if(lat==0){
if(now==0){
g[++tot]=cs;
for(rg int i=0;i<g[tot].size();i++){
rg int u=g[tot][i];
sum[tot]+=1LL*u*(u-1)/2%mod;
if(sum[tot]>=mod) sum[tot]-=mod;
}
}
return;
}
dfs(now,lat-1);
if(now>=lat){
cs.push_back(lat);
dfs(now-lat,lat);
cs.pop_back();
}
}
int main(){
scanf("%d",&n);
m=(n-1)*n/2;
rg int aa;
for(rg int i=1;i<n;i++){
scanf("%d",&aa);
vis[aa]=1;
}
dfs(n,n);
for(rg int i=1;i<=tot;i++){
std::reverse(g[i].begin(),g[i].end());
mp[g[i]]=i;
}
f[0][1]=1;
for(rg int i=0;i<m;i++){
for(rg int j=1;j<=tot;j++){
if(f[i][j]){
if(vis[i+1]){
for(rg int k=0;k<g[j].size();k++){
for(rg int o=k+1;o<g[j].size();o++){
cs.clear();
cs.push_back(g[j][k]+g[j][o]);
for(rg int p=0;p<g[j].size();p++){
if(p!=k && p!=o){
cs.push_back(g[j][p]);
}
}
std::sort(cs.begin(),cs.end());
f[i+1][mp[cs]]+=1LL*f[i][j]*g[j][k]%mod*g[j][o]%mod;
if(f[i+1][mp[cs]]>=mod) f[i+1][mp[cs]]-=mod;
}
}
} else {
f[i+1][j]+=1LL*f[i][j]*(sum[j]-i)%mod;
if(f[i+1][j]>=mod) f[i+1][j]-=mod;
}
}
}
}
printf("%d\n",f[m][tot]);
return 0;
}
2020.12.16 模拟赛x+1的更多相关文章
- 【2020.8.23NOIP模拟赛】失落
[ 2020.8.23 N O I P 模 拟 赛 ] 失 落 [2020.8.23NOIP模拟赛]失落 [2020.8.23NOIP模拟赛]失落 题目描述 出题人心情很失落,于是他直接告诉你让你求出 ...
- 2020.3.23 模拟赛游记 & 题解
这次的模拟赛,实在是水. 数据水,\(\texttt{std}\) 水,出题人水,做题人也水.??? 游记就说一句: 水. T1 metro 弱智题. 人均 \(100pts\). #pragma G ...
- [ZROI 9.16模拟赛] Tutorial
Link: 传送门 A: 套路题结果想了好久…… 排序二叉树的性质就是中序遍历单调递增 于是只考虑当前树的中序遍历的序列即可,与树的形态无关 将序列改成严格单调增想到最大化不变的数,但直接LIS求的是 ...
- 12.25模拟赛T1
可以区间dp,但是复杂度太高. 所以应该是贪心,怎么贪心呢? 这种题目,最好还是手玩找一些规律. 可以发现,由于保证可以m次填完,所以颜色之间没有相互包含关系. 比较像分治的模型. 所以考虑拿到一个区 ...
- 2018.02.12 noip模拟赛T2
二兵的赌注 Description游戏中,二兵要进入了一家奇怪的赌场.赌场中有n个庄家,每个庄家都可以猜大猜小,猜一次一元钱.每一次开彩前,你都可以到任意个庄家那里下赌注.如果开彩结果是大,你就可以得 ...
- 12.25模拟赛T3
可以发现,答案O(根号)(因为链上答案最大,n/2,n/3...根号种) 每次求答案要二分 优秀的做法是: 对于小于根号n的暴力nlogn找,可能二分到同一个mid,记忆化一下最小的tot值 对于大于 ...
- 12.25模拟赛T2
https://www.luogu.org/blog/a23333/post-xing-xuan-mu-ni-sai-path-ji-wang-zui-duan-lu 如果设f[i]表示从i到n的期望 ...
- [8.16模拟赛] 玩具 (dp/字符串)
题目描述 儿时的玩具总是使我们留恋,当小皮还是个孩子的时候,对玩具更是情有独钟.小皮是一个兴趣爱好相当广泛且不专一的人,这这让老皮非常地烦恼.也就是说,小皮在不同时刻所想玩的玩具总是会不同,而有心的老 ...
- 【2019.8.12 慈溪模拟赛 T1】钥匙(key)(暴力DP)
暴力\(DP\) 这题做法很多,有\(O(n^2)\)的,有\(O(n^2logn)\)的,还有徐教练的\(O(nlogn)\)的,甚至还有\(bzt\)的二分+线段树优化建图的费用流. 我懒了点,反 ...
随机推荐
- 最全JVM与性能调优知识点总结,看看哪些是你还没掌握的?
前言 JVM调优是每个高级程序员的必修课,在本章中,我会从发展过程以及核心价值来剖析JVM的体系结构.为了让大家更好的理解JVM的工作机制, 我会在讲解完运行时数据区之后,再通过一个类的加载过程到这个 ...
- 又陷入知识盲区了,面试被问SpringBoot集成dubbo,我当时就懵了
前言 前两天在和粉丝聊天的时候,粉丝跟我说之前在面试的时候被问到SpringBoot这一块的知识被问的有点懵,和我问了不少这方面的东西.事后我想了想不如把这些东西分享出来吧,让更多的人看到,这样不管是 ...
- zabbix的搭建及操作(1)server-client架构
实验环境 Server端 Centos7:192.168.10.10 server.zabbix.com 可连外网 Agent 端 Centos7:192.168.10.20 ...
- 使用Folx智能速控功能,确保带宽资源的合理分配
市面上的大部分下载软件,都会配备速度控制的功能,用于限制下载任务的带宽占用.但除此之外,Folx专业版还提供了更加智能化的速度控制功能,用户可以为速控指定更加详细的条件,比如程序限制条件.时间限制条件 ...
- 有什么OCR文字识别软件好用?
OCR文字识别是指:对文本资料进行扫描,然后对图像文件进行分析处理,最后获取文字以及版面信息的过程.对于许多学生党而言,一款好用的文字识别软件,能节省很多抄笔记的时间,而对于许多处理文字内容的白领而言 ...
- 下载器Folx教程:智能标签怎么用?
Mac专用下载器Folx的智能标签中内置了图片标签,可以自动分类图片文件,但要如何分类GIF图片呢?其实,我们可以在Folx的标签面板创建动图标签,然后再创建标签专属的下载文件夹,来独立存放GIF格式 ...
- 「LOJ 541」「LibreOJ NOIP Round #1」七曜圣贤
description 题面很长,这里给出题目链接 solution 用队列维护扔掉的红茶,同时若后扔出的红茶比先扔出的红茶编号更小,那么先扔出的红茶不可能成为答案,所以可以用单调队列维护 故每次询问 ...
- 【R语言入门】R语言中的变量与基本数据类型
说明 在前一篇中,我们介绍了 R 语言和 R Studio 的安装,并简单的介绍了一个示例,接下来让我们由浅入深的学习 R 语言的相关知识. 本篇将主要介绍 R 语言的基本操作.变量和几种基本数据类型 ...
- jmp使用
jps -l jmap 36429 jmap -heap 36429 jmap -histo:live 36429 jmap -clstats 36429 jmap -finalizerinfo 3 ...
- 【PSMA】Progressive Sample Mining and Representation Learning for One-Shot Re-ID
目录 主要挑战 主要的贡献和创新点 提出的方法 总体框架与算法 Vanilla pseudo label sampling (PLS) PLS with adversarial learning Tr ...