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/队爷的讲学计划 题解:刚开始理解题意理解了好半天,然后发 ...
随机推荐
- 编译 OpenCV 的 Python 依赖
这一次编译 OpenCV 的 Python 依赖为了方便运行我们使用 Docker 进行编译,环境准备如下: 系统依赖:Ubuntu 18.04 Python 版本:3.6,Ubuntu 18.04 ...
- 使用ollama + AnythingLLM快速且简单的在本地部署llm3
使用ollama + AnythingLLM快速且简单的在本地部署llm3 不多说,直接开始 一.安装ollama ollama官网:https://ollama.com/ 下载地址:https:// ...
- API 开发的后盾:平台工程提供强力动态支持
过去几年,开发团队一直在发展传统的 DevOps.一些开发人员认为,CloudOps 或 DeploymentOps 等新实践的兴起将会导致回到孤岛问题.其他人则不愿意在承担所有其他职责之外构建.部署 ...
- 云效故障定位研究论文被ICSE 2021 SEIP track收录
近期,由阿里云云效团队联合复旦大学CodeWisdom研究团队.阿里技术风险部安全生产团队,合作完成的论文<MicroHECL: High-Efficient Root Cause Locali ...
- OpenKruise v0.8.0 核心能力解读:管理 Sidecar 容器的利器
简介: OpenKruise 是阿里云开源的云原生应用自动化管理套件,也是当前托管在 Cloud Native Computing Foundation (CNCF) 下的 Sandbox 项目.它来 ...
- Redis 7.0 Multi Part AOF的设计和实现
简介:本文将详解Redis中现有AOF机制的一些不足以及Redis 7.0中引入的Multi Part AOF的设计和实现细节. Redis 作为一种非常流行的内存数据库,通过将数据保存在内存中,R ...
- dotnet 警惕 C# 的 is var 写法
本文将和大家介绍 C# 语言设计里面,我认为比较坑的一个语法.通过 is var 的写法,会让开发者误以为 null 是不被包含的,然而事实是在这里的 var 是被赋予含义的,将被允许 null 通过 ...
- Taurus.MVC 微服务框架 入门开发教程:项目集成:7、微服务间的调用方式(调整):引用程序集及代码下载(新增)
前言: 今天补充一下 Taurus.MVC 微服务教程,介绍一下微服务中针对RPC方面调整或新增的功能. 之前系列文章目录: Taurus.MVC 微服务框架 入门开发教程:项目集成:1.服务端:注册 ...
- 如何将本地项目第一次同步到gitee远程
一,Gitee账号的注册/登录 在gitee登录入口输入相关信息进行注册登录https://gitee.com/signup#lang=zh-CN 二,本地安装git客户端并配置用户信息 1.Git ...
- Oracle、达梦:获取两个表中差异的数据:minus(减法)
Oracle.达梦:获取两个表中差异的数据:minus(减法) mysql没有.需要用别的方式替换 表结构必须一致,数据也必须一致才能减去 真实意思:T_1中的数据减去T_2中的数据.返回还多余的数据 ...