NOIP模拟62
T1 Set
解题思路
抽屉原理
发现对于前缀和向 \(n\) 取模之后一定是右两个值相等的(包括什么都不选的 0 )。
假设 \(pre_j=pre_i\) 那么 \([j+1,i]\) 之间这一段数字的和一定是 \(n\) 的倍数。
code
#include<bits/stdc++.h>
#define int long long
#define ull unsigned long long
#define f() cout<<"Failed"<<endl
using namespace std;
inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
return x*f;
}
const int N=1e6+10,M=1e3+10;
int n,m,s[N],pre[N],las[N];
signed main()
{
freopen("a.in","r",stdin); freopen("a.out","w",stdout);
memset(las,-1,sizeof(las)); n=read(); las[0]=0;
for(int i=1;i<=n;i++)
{
s[i]=read()%n;
pre[i]=(pre[i-1]+s[i])%n;
if(las[pre[i]]!=-1)
{
printf("%lld\n",i-las[pre[i]]);
for(int j=las[pre[i]]+1;j<=i;j++)
printf("%lld ",j);
exit(0);
}
las[pre[i]]=i;
}
return 0;
}
T2 Read
解题思路
发现内存限制了我们的想象(其实我考场上看错题了。。)
发现对于有一种书的个数大于其他书的个数之和 +1 答案才不是 0 。
因此,可以 \(n\) 的复杂度扫一遍,用两个变量id, cnt, cnt 初始为0。
然后生成每一个 \(A_i\) , 如果 \(cnt=0\) , 那么就令 \(id=A[i],cnt=1\) , 否则如果 \(id==A[i]\) , 则 \(cnt++\) , 如果不等于, \(cnt--\) 。
最后只要再扫一遍求出id 的出现次数即可。
code
#include<bits/stdc++.h>
#define int long long
#define ull unsigned long long
#define f() cout<<"Failed"<<endl
using namespace std;
inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
return x*f;
}
const int N=5e7+10,Mx=1e3+10;
int M,K,n,all,cnt,id,Num[Mx],X[Mx],Y[Mx],Z[Mx];
void init()
{
M=read(); K=read();
for(int i=1;i<=M;i++) Num[i]=read(),n+=Num[i];;
for(int i=1;i<=M;i++) X[i]=read();
for(int i=1;i<=M;i++) Y[i]=read();
for(int i=1;i<=M;i++) Z[i]=read();
int S=(1<<K)-1,len=0;
for(int i=1,temp;i<=M;i++)
{
temp=X[i]; int las=X[i];
if(!cnt) id=temp,cnt=1;
else if(id==temp) cnt++;
else cnt--;
for(int j=1;j<Num[i];j++)
{
las=(las*Y[i]+Z[i])&S;
temp=las;
if(!cnt) id=temp,cnt=1;
else if(id==temp) cnt++;
else cnt--;
}
}
}
void work()
{
int S=(1<<K)-1,len=0;
for(int i=1,temp;i<=M;i++)
{
temp=X[i]; int las=X[i]; all+=(temp==id);
for(int j=1;j<Num[i];j++)
{
las=(las*Y[i]+Z[i])&S;
temp=las; all+=(temp==id);
}
}
}
signed main()
{
freopen("b.in","r",stdin); freopen("b.out","w",stdout);
init(); work(); printf("%lld",(all<=(n+1)/2)?0:all-(n-all)-1);
return 0;
}
T3 题目交流通道
解题思路
好像是个容斥经典题(尽管我不会)。。
对于每一个距离为 0 的联通块给缩起来,称为团。
两个团之间的点的距离是一定的,那么就要考虑重边的情况,假设有 \(a\) 条边重复,如果存在 \(k\) 使得 \(d_{i,j}=d_{i,k}+d_{j,k}\) ,那么剩下所有的边只要大于等于 \(d_{i,j}\) 就可以了,方案数是 \((K-d_{i,j}+1)^a\)
如果不存在的话至少有一条边要等于 \(d_{i,j}\) 就好了,所以在上述情况的方案数中除去都是 大于 \(d_{i,j}\) 的情况,也就是 \((K-d_{i,j}+1)^a-(K-d_{i,j})^a\)
考虑处理团内部的边,然后经典的容斥就来了: \(f_i\) 表示 \(i\) 个点距离为 0 的方案数, \(g_i\) 表示不管是否合法 \(i\) 个点的图的方案数。
就有 \(g_i=(K+1)^{\binom{i}{2}}\) 也就是取值的边数次方。
\]
那么为什么组合系数是 \(\binom{i-1}{j-1}\) 呢,枚举时我们把图分成了两个部分:已知合法的和未知的。
那么显然未知的部分包含了一部分合法的团,为了防止重复,我们钦定枚举的是 1 节点(也可以钦定别的节点)所在的团是合法的部分,这样就相当于是从 \(i-1\) 个点中选择 \(j-1\) 个点与 1 节点联通。
code
#include<bits/stdc++.h>
#define int long long
#define ull unsigned long long
#define f() cout<<"Failed"<<endl
using namespace std;
inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
return x*f;
}
const int N=410,mod=998244353;
int n,m,ans=1,siz[N],fac[N],ifac[N],dis[N][N],f[N],g[N],fa[N];
int find(int x){if(fa[x]==x) return x;return fa[x]=find(fa[x]);}
int C(int x,int y,int p=mod){return fac[x]*ifac[y]%p*ifac[x-y]%p;}
int power(int x,int y,int p=mod){int temp=1;while(y){if(y&1) temp=temp*x%p;x=x*x%p;y>>=1;}return temp;}
signed main()
{
freopen("c.in","r",stdin); freopen("c.out","w",stdout);
n=read(); m=read();
fac[0]=ifac[0]=1; for(int i=1;i<=n;i++) fac[i]=fac[i-1]*i%mod,g[i]=f[i]=power(m+1,i*(i-1)/2),fa[i]=i;
ifac[n]=power(fac[n],mod-2); for(int i=n-1;i>=1;i--) ifac[i]=ifac[i+1]*(i+1)%mod;
for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) dis[i][j]=read();
for(int i=1;i<=n;i++) if(dis[i][i]) printf("0"),exit(0);
for(int i=1;i<=n;i++) for(int j=1;j<i;j++) if(dis[i][j]!=dis[j][i]||dis[i][j]>m) printf("0"),exit(0);
for(int i=1;i<=n;i++) for(int j=1;j<i;j++) for(int k=1;k<=n;k++) if(dis[i][k]+dis[k][j]<dis[i][j]) printf("0"),exit(0);
for(int i=1;i<=n;i++) for(int j=1;j<i;j++) f[i]=(f[i]-f[j]*g[i-j]%mod*C(i-1,j-1)%mod*power(m,j*(i-j))%mod+mod)%mod;
for(int i=1;i<=n;i++) for(int j=1;j<i;j++) if(!dis[i][j]&&find(i)!=find(j)) fa[find(i)]=find(j);
for(int i=1;i<=n;i++) siz[find(i)]++;
for(int i=1;i<=n;i++) if(find(i)==i) ans=ans*f[siz[i]]%mod;
for(int i=1;i<=n;i++)
for(int j=1,k;j<i;j++)
if(find(i)==i&&find(j)==j)
{
for(k=1;k<=n;k++) if(dis[i][k]&&dis[k][j]&&dis[i][k]+dis[k][j]==dis[i][j]) break;
if(k<=n) ans=ans*power(m-dis[i][j]+1,siz[i]*siz[j])%mod;
else ans=ans*(power(m-dis[i][j]+1,siz[i]*siz[j])-power(m-dis[i][j],siz[i]*siz[j]))%mod;
}
printf("%lld",ans);
return 0;
}
T4 题目难度提升
解题思路
貌似我的做法被 Hack 了(OJ 可以过就行。。),大概是细节处理不到位吧。
其实就是题解的做法,有了那两个思想时候我们就可以开两个 set 维护已经加入的数字以及剩下的数字。
加入我们需要查询 \((m,k)\) 之间是否有数字被放进去,可以直接在维护放入数字的 set 中查找第一个大于 \(m\) 数字,看他与 \(k\) 的大小关系。
对于每一次中位数的维护可以维护中间的两个数字什么然后就没啥了。。。
code
#include<bits/stdc++.h>
#define int long long
#define ull unsigned long long
#define f() cout<<"Failed"<<endl
using namespace std;
inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
return x*f;
}
const int N=1e5+10,INF=1e18;
int n,cnt,ans[N];
double mid,s[N];
bool flag;
multiset<double> se,in;
void solve1(int i)
{
double num=(*se.upper_bound(mid)),temp=*in.upper_bound(mid),r=2*num-mid;
if(temp<num) ans[i]=(*se.rbegin()),mid=(mid+temp)/2.0;
else if(temp<=r) ans[i]=(*se.rbegin()),mid=(mid+temp)/2.0;
else ans[i]=(*(--se.upper_bound(r))),mid=(mid+1.0*ans[i])/2.0;
se.erase(se.find(ans[i])); in.insert(ans[i]);
}
void solve2(int i)
{
double num=*se.lower_bound(mid),temp=*in.upper_bound(mid);
if(temp<num) ans[i]=(*se.rbegin()),mid=temp;
else ans[i]=num,mid=num;
se.erase(se.find(ans[i])); in.insert(ans[i]);
}
void solve()
{
mid=ans[1]=(*se.begin()); se.erase(se.find(ans[1]));
in.insert(s[1]); in.insert(INF);
for(int i=2;i<=n;i++)if(i&1) solve2(i); else solve1(i);
for(int i=1;i<=n;i++) printf("%lld ",ans[i]); exit(0);
}
signed main()
{
freopen("d.in","r",stdin); freopen("d.out","w",stdout);
n=read(); for(int i=1;i<=n;i++) s[i]=read(),se.insert(s[i]);
sort(s+1,s+n+1);
for(int i=2;i<=n;i++) if(s[i]==s[i-1]){flag=true;break;}
if(!flag) solve();
if(n&1) mid=s[n/2+1];
else mid=(1.0*s[n/2]+1.0*s[n/2+1])/2.0;
int pos=upper_bound(s+1,s+n+1,mid)-s-1,r,poi=n,i;
for(int i=2;i<=pos;i++) if(s[i]==s[i-1]){flag=false;break;}
if(flag) solve();
for(int i=pos-1;i>=1;i--)if(s[i]==s[i+1]){r=s[i];pos=i-1;break;}
in.insert(r); in.insert(r); in.insert(INF); mid=r;
se.erase(se.find(r)); se.erase(se.find(r));
ans[++cnt]=r; ans[++cnt]=r;
for(i=pos;i>=1&&poi>pos+2;i--)
{
ans[++cnt]=s[poi]; ans[++cnt]=s[i];
se.erase(se.find(s[i])); se.erase(se.find(s[poi]));
in.insert(s[i]); in.insert(s[poi]);
poi--;
}
while(cnt<n) pos=*se.rbegin(),ans[++cnt]=pos,in.insert(pos),se.erase(se.find(pos));
for(int i=1;i<=n;i++) printf("%lld ",ans[i]);
return 0;
}
NOIP模拟62的更多相关文章
- Noip模拟62 2021.9.26
T1 Set 真就随机化拿了$90$?? 不过还是有依据的,毕竟这道题出解的几率很大,随出答案的概率也极大 所以不妨打一个随机化 1 #include<bits/stdc++.h> 2 # ...
- 2021.9.26考试总结[NOIP模拟62]
T1 set 从\(0\)到\(n\)前缀余数有\(n+1\)个,但只有\(n\)种取值,找到一样的两个输出区间即可. \(code:\) T1 #include<bits/stdc++.h&g ...
- NOIP模拟17.9.22
NOIP模拟17.9.22 前进![问题描述]数轴的原点上有一只青蛙.青蛙要跳到数轴上≥
- NOIP 模拟4 T2
本题属于二和一问题 子问题相互对称 考虑对于问题一:知a求b 那么根据b数组定义式 显然能发现问题在于如何求dis(最短路) 有很多算法可供选择 dijsktra,floyed,bfs/dfs,spf ...
- 2021.9.17考试总结[NOIP模拟55]
有的考试表面上自称NOIP模拟,背地里却是绍兴一中NOI模拟 吓得我直接文件打错 T1 Skip 设状态$f_i$为最后一次选$i$在$i$时的最优解.有$f_i=max_{j<i}[f_j+a ...
- NOIP模拟赛20161022
NOIP模拟赛2016-10-22 题目名 东风谷早苗 西行寺幽幽子 琪露诺 上白泽慧音 源文件 robot.cpp/c/pas spring.cpp/c/pas iceroad.cpp/c/pas ...
- contesthunter暑假NOIP模拟赛第一场题解
contesthunter暑假NOIP模拟赛#1题解: 第一题:杯具大派送 水题.枚举A,B的公约数即可. #include <algorithm> #include <cmath& ...
- NOIP模拟赛 by hzwer
2015年10月04日NOIP模拟赛 by hzwer (这是小奇=> 小奇挖矿2(mining) [题目背景] 小奇飞船的钻头开启了无限耐久+精准采集模式!这次它要将原矿运到泛光之源的矿 ...
- 大家AK杯 灰天飞雁NOIP模拟赛题解/数据/标程
数据 http://files.cnblogs.com/htfy/data.zip 简要题解 桌球碰撞 纯模拟,注意一开始就在袋口和v=0的情况.v和坐标可以是小数.为保险起见最好用extended/ ...
- 队爷的讲学计划 CH Round #59 - OrzCC杯NOIP模拟赛day1
题目:http://ch.ezoj.tk/contest/CH%20Round%20%2359%20-%20OrzCC杯NOIP模拟赛day1/队爷的讲学计划 题解:刚开始理解题意理解了好半天,然后发 ...
随机推荐
- 抓包整理————wireshark DNS 演练[三]
前言 简单整理一些wireshark dns 演练. 正文 简单介绍一下什么是dns. 这个其实可以百度一下哈,其实就是将域名转换为ip. 然后查询过程是这样的: 根域名服务器 权威服务器 dns 被 ...
- 鸿蒙HarmonyOS实战-ArkUI动画(布局更新动画)
前言 动画是一种通过连续展示一系列静止的图像(称为帧)来创造出运动效果的艺术形式.它可以以手绘.计算机生成或其他各种形式呈现.在动画中,每一帧都具有微小的变化,当这些帧被快速播放时,人眼会产生视觉上的 ...
- nethttp和gin 路由
net/http 路由注册 func test1() { http.HandleFunc("/", func(w http.ResponseWriter, r *http.Requ ...
- 阿里云云原生加速器企业硬之城携手阿里云 Serverless 应用引擎(SAE)打造低代码平台
简介: 作为入选阿里云首期云原生加速器的企业,硬之城此前也获得了阿里云首批产品生态集成认证,通过云原生加速器项目携手阿里云共建更加丰富的云原生产业生态圈,加速云原生落地. 作者 | 陈泽涛(硬之城产品 ...
- RocketMQ 消息集成:多类型业务消息-普通消息
简介: 本篇将从业务集成场景的诉求开始,介绍 RocketMQ 作为业务消息集成方案的核心能力和优势,通过功能场景.应用案例以及最佳实践等角度介绍 RocketMQ 普通消息类型的使用. 引言 Apa ...
- 日处理数据量超10亿:友信金服基于Flink构建实时用户画像系统的实践
导读:当今生活节奏日益加快,企业面对不断增加的海量信息,其信息筛选和处理效率低下的困扰与日俱增.由于用户营销不够细化,企业 App 中许多不合时宜或不合偏好的消息推送很大程度上影响了用户体验,甚至引发 ...
- 爱奇艺在 Dubbo 生态下的微服务架构实践
简介: 本文整理自作者于 2020 年云原生微服务大会上的分享<爱奇艺在 Dubbo 生态下的微服务架构实践>,重点介绍了爱奇艺在 Dubbo.Sentinel 等开发框架方面的使用经验以 ...
- KubeVela:标准化的云原生平台构建引擎
简介: 本文由"GO 开源说"第三期 KubeVela 直播内容修改整理而成,视频内容较长,本文内容有所删减和重构. KubeVela 的背景 KubeVela 是一个基于 Go ...
- 自己动手写符合自己业务需求的eslint规则
简介:eslint是构建在AST Parser基础上的规则扫描器,缺省情况下使用espree作为AST解析器.rules写好对于AST事件的回调,linter处理源代码之后会根据相应的事件来回调ru ...
- [K8s] Docker 单节点部署 Rancher
Rancher 是通过 Web 界面管理 k8s 集群的工具,本身支持使用 Docker 启动. 单节点部署只需要 docker run 即可,易用性高,高可用部署可以使用 nginx 反向代理机制. ...