7.12考试总结(NOIP模拟12)[简单的区间·简单的玄学·简单的填数]
即使想放弃,也没法放弃最想要的东西,这就是人
前言
这次应该是和 SDFZ 一起打的第一场比赛吧。
然而我还是 FW 一个。。。
这次考试也有不少遗憾,主要的问题是码力不足,不敢去直面正解,思考程度不够。
改题也比较费劲,记录:
T1 简单的区间
背景
这个题和上一场比赛的第三题一样令人感到亲切,还是在第一时间内想到了单调栈求左右边界。
然后就想到了昨天考试题的恶心程度,想都没想,码完一个单调栈优化的暴力之后就走了。
得分:30pts(\(code\));
解题思路
这个题的做法其实有三种,一种是递归运算的正解,另一种是码量极大的主席树(可持久化权值线段树记录个数)。
这里分别给出官方题解和 zxb 的\(code\);
然后就是来自于 pyt 的 vetor 做法了。
第一步也是运用单调栈求出左右区间,再次不做过多赘述。
接下来就是类似于入阵曲的做法了,求出前缀和(存到 q 数组里)后对于 \(\bmod\;k\) 意义下的不同的余数的数量。
然后就是运用启发式合并的思想进行处理了。
对于暴力左区间的情况,假设当前扫到了 i 合法节点为 j 最大值的下标为 pos 。
满足 \(q_j\) 与 \(q_i+s_{pos}\) 在 \(\bmod\;k\) 意义下相同的序列就是 k 的倍数。
因为,我们只需要在右区间内的符合条件的点的个数。
所以,直接在 vector 里二分查找出右端点和 pos 在 vector 中的下标,相减就是个数了。
同样的 对于暴力右区间的算法也是如此,有一些不同。
- 注意: 在存储余数为 0 的 vector 数组里要先放进去一个 0 ,因为在暴力右区间的时候会有左端点-1,可能会在序列里没有这个数,并且与入阵曲相似,前零位和的余数也为 0 ,
- 另外,还有注意一下前缀和的区间端点问题。
code
#include<bits/stdc++.h>
#define int long long
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=5e6+10,M=5e6+10;
int n,mod,ans,top,s[N],sta[N],l[N],r[N],q[N];
vector<int> v[M];
inline void Sta_Init()
{
sta[++top]=1;
l[1]=1;
for(int i=2;i<=n;i++)
{
while(top&&s[sta[top]]<=s[i])
{
r[sta[top]]=i-1;
top--;
}
l[i]=sta[top]+1;
sta[++top]=i;
}
while(top) r[sta[top--]]=n;
}
inline int workl(int li,int ri,int pos)
{
int sum=0;
for(int i=li;i<=pos;i++)
{
int res=(q[i-1]+s[pos]%mod+mod)%mod;
int ls=lower_bound(v[res].begin(),v[res].end(),pos)-v[res].begin();
int rs=upper_bound(v[res].begin(),v[res].end(),ri)-v[res].begin();
sum+=max(rs-ls,0ll);
}
return sum;
}
inline int workr(int li,int ri,int pos)
{
int sum=0;
for(int i=pos;i<=ri;i++)
{
int res=(q[i]-s[pos]%mod+mod)%mod;
int ls=lower_bound(v[res].begin(),v[res].end(),li-1)-v[res].begin();
int rs=upper_bound(v[res].begin(),v[res].end(),pos-1)-v[res].begin();
sum+=max(rs-ls,0ll);
}
return sum;
}
#undef int
int main()
{
#define int register long long
#define ll long long
n=read();
mod=read();
for(int i=1;i<=n;i++)
s[i]=read();
Sta_Init();
for(int i=1;i<=n;i++)
q[i]=(q[i-1]+s[i])%mod;
v[0].push_back(0);
for(int i=1;i<=n;i++)
v[q[i]%mod].push_back(i);
for(int i=1;i<=n;i++)
if(i-l[i]<r[i]-i)
ans+=workl(l[i],r[i],i);
else ans+=workr(l[i],r[i],i);
printf("%lld",ans-n);
return 0;
}
T2 简单的玄学
背景
对于 70pts 的柿子,相信各位都可以很快地搞掉:
\]
也就是:
\]
不难发现对于 \(m<10^6\) 的数据,直接暴力算 \(2^n\) 后的 m 项,然后求一个 \(\gcd\) 就可以了。
但是,取 \(\bmod\) 之后的 \(\gcd\) 就不是原来的 \(\gcd\) 了!
例如:7 和 11 在 \(\bmod\;4\) 的意义下的 \(\gcd\) 是 3 但是他们本身的 \(\gcd\) 是 1 。
于是我们骗到 70pts 的幻想破灭了(可惜考场上的我太傻没有想到这个反例。。)
让我们看一下官方题解:
意会一下之后,我们发现分母的约数只能是 2 的倍数,然后我们就可以求分子上阶乘的 2 的次数。
发现是有一定规律的:每隔 \(2^i\) 就会有一个 \(2^i\) 的倍数,所以就可以 \(\mathcal{O(log_2m)}\) 求出。
但是,更大的该怎么办呢??,不难发现,如果 \(m>\bmod\) 那么分子在 取 \(\bmod\) 之后一定是 0 ,
因此我们只需要求出公约数之后输出两次分母就好了。
code
#include<bits/stdc++.h>
#define int long long
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 mod=1e6+3;
int n,m,base,ans=1;
inline int ksm(int x,int p)
{
int ans=1;
p=p%(mod-1);
while(p)
{
if(p&1) ans=ans*x%mod;
p>>=1;
x=x*x%mod;
}
return ans;
}
#undef int
int main()
{
#define int long long
#define ll long long
n=read();
m=read();
base=ksm(2,n);
int poww=1,sum=0;
while((poww=poww*2)<=m-1)
sum+=(m-1)/poww;
if(m>=mod)
{
int tmp=ksm(ksm(2,sum),mod-2);
base=tmp*ksm(base,m-1)%mod;
printf("%lld %lld",base,base);
return 0;
}
for(int i=1;i<m;i++)
ans=ans*(base-i)%mod;
ans=ans*ksm(ksm(2,sum%(mod-1)),mod-2)%mod;
base=ksm(2,(((m-1)%(mod-1))*(n%(mod-1))+mod-1-sum)%(mod-1))%mod;
printf("%lld %lld",(base-ans+mod)%mod,base%mod);
return 0;
}
T3 简单的填数
背景
这个题思考的不多,码了个暴力就走了,然后小的数据点 TLE 大的直接 WA ,人傻了。
解题思路
先看一下官方题解:
然后我们发现根本看不懂。。。
开两个 pair 数组分别记录贪心到现在位置的最大值以及现在最大值的数量(也就是 up)。
同样的,用 down 记录最小值以及其数量。
对于没有数的位置,直接贪心的向后算就好了( up 类似于二进制, down 类似于五进制)。
对于有数的位置(假设现在要填进去的数为 up 和 down ,现在有的数是 s[i])分为以下几种情况
\(s_i>up\) 或者 \(s_i<down\) 表示这个序列不可能实现,直接输出 -1 。
\(s_i=up\) 或者 \(s_i=down\) 直接该怎样算怎样算就好了。
\(s_i<up\) 对于 up 的值,储存为 \(s_i\),数量记为 2 (因为后面的数要尽量地大)。
\(s_i>down\) 同样的,对于 down 值,也是储存为 \(s_i\) ,但是数量要储存为 1 (因为后面的要尽量的小)。
剩下的就与 down 没有什么关系了,主要运用 up 数组 逆推,特判一下第 n 位,之后尽量对于没有数的挑着大的选就好了,需要用一个数组记录一下每一个数的出现次数。
code
#include<bits/stdc++.h>
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=2e5+10;
int n,ans[N],s[N],vis[N];
pair<int,int> up[N],down[N];
inline void Up_True(int pos,int num)
{
if(num<s[pos])
{
cout<<-1;
exit(0);
}
up[pos].first=s[pos];
up[pos].second=2;
}
inline void Up_False(int pos)
{
if(up[pos-1].second==1)
{
up[pos].first=up[pos-1].first;
up[pos].second=2;
return ;
}
up[pos].first=up[pos-1].first+1;
up[pos].second=1;
}
inline void Get_Up()
{
for(int i=2;i<=n;i++)
{
int temp;
if(up[i-1].second==2) temp=up[i-1].first+1;
else temp=up[i-1].first;
if(s[i]&&s[i]!=temp) Up_True(i,temp);
else Up_False(i);
}
}
inline void Down_True(int pos,int num)
{
if(num>s[pos])
{
cout<<-1;
exit(0);
}
down[pos].first=s[pos];
down[pos].second=1;
}
inline void Down_False(int pos)
{
if(down[pos-1].second<5)
{
down[pos].first=down[pos-1].first;
down[pos].second=down[pos-1].second+1;
return ;
}
down[pos].first=down[pos-1].first+1;
down[pos].second=1;
}
inline void Get_Down()
{
for(int i=2;i<=n;i++)
{
int temp;
if(down[i-1].second==5) temp=down[i-1].first+1;
else temp=down[i-1].first;
if(s[i]&&s[i]!=temp) Down_True(i,temp);
else Down_False(i);
}
}
int main()
{
n=read();
for(int i=1;i<=n;i++)
s[i]=read();
up[1].first=up[1].second=down[1].first=down[1].second=1;
Get_Up();
Get_Down();
if(!s[n]) vis[ans[n]=up[n-1].first]++;
else ans[n]=s[n];
for(int i=n-1;i>=1;i--)
{
ans[i]=min(up[i].first,ans[i+1]);
if(vis[ans[i]]>=5) ans[i]--;
vis[ans[i]]++;
}
printf("%d\n",ans[n]);
for(int i=1;i<=n;i++)
printf("%d ",ans[i]);
return 0;
}
7.12考试总结(NOIP模拟12)[简单的区间·简单的玄学·简单的填数]的更多相关文章
- 2021.8.12考试总结[NOIP模拟37]
T1 数列 考场上切掉的简单题. $a$,$b$与数列中数的正负值对答案无关.全当作正数计算即可. $exgcd$解未知数系数为$a$,$b$,加和为$gcd(a,b)$的不定方程组,再枚举每个数.如 ...
- 2021.9.12考试总结[NOIP模拟51]
T1 茅山道术 仔细观察发现对于每个点只考虑它前面第一个与它颜色相同的点即可. 又仔细观察发现对一段区间染色后以这个区间内点为端点的区间不能染色. 于是对区间右端点而言,区间染色的贡献为遍历到区间左端 ...
- [考试总结]noip模拟12
菜 今天总体来说 菜爆了,打了 \(3\) 个暴力,没有一个是正解,并且每一个分数都低得要命... 主要还是太菜了... 第一题开题发现和昨天 \(T3\) 一样,然而因为还没学可持久化数据结构就咕掉 ...
- 2021.10.12考试总结[NOIP模拟75]
T1 如何优雅的送分 考虑式子的实际意义.\(2^{f_n}\)实际上就是枚举\(n\)质因子的子集.令\(k\)为这个子集中数的乘积,就可以将式子转化为枚举\(k\),计算\(k\)的贡献. 不难得 ...
- noip模拟12[简单的区间·简单的玄学·简单的填数]
noip模拟12 solutions 这次考试靠的还是比较好的,但是还是有不好的地方, 为啥嘞??因为我觉得我排列组合好像白学了诶,文化课都忘记了 正难则反!!!!!!!! 害没关系啦,一共拿到了\( ...
- 6.17考试总结(NOIP模拟8)[星际旅行·砍树·超级树·求和]
6.17考试总结(NOIP模拟8) 背景 考得不咋样,有一个非常遗憾的地方:最后一题少取膜了,\(100pts->40pts\),改了这么多年的错还是头一回看见以下的情景... T1星际旅行 前 ...
- 5.23考试总结(NOIP模拟2)
5.23考试总结(NOIP模拟2) 洛谷题单 看第一题第一眼,不好打呀;看第一题样例又一眼,诶,我直接一手小阶乘走人 然后就急忙去干T2T3了 后来考完一看,只有\(T1\)骗到了\(15pts\)[ ...
- 5.22考试总结(NOIP模拟1)
5.22考试总结(NOIP模拟1) 改题记录 T1 序列 题解 暴力思路很好想,分数也很好想\(QAQ\) (反正我只拿了5pts) 正解的话: 先用欧拉筛把1-n的素数筛出来 void get_Pr ...
- Noip模拟12 2021.7.12
T1 interval 亏得昨天晚上改掉了T3并且理解了单调栈,今天一扫这题目就知道要用啥了. 先预处理出以a[i]为最大值的最大左右区间.然后再将a[i]取%!!!是的,要不然会影响单调栈的使用.. ...
- 2021.9.17考试总结[NOIP模拟55]
有的考试表面上自称NOIP模拟,背地里却是绍兴一中NOI模拟 吓得我直接文件打错 T1 Skip 设状态$f_i$为最后一次选$i$在$i$时的最优解.有$f_i=max_{j<i}[f_j+a ...
随机推荐
- VulnHub-Jangow-01-1.0.1打靶记录
知识点 NMAP参数 -sV 获取系统信息 -sT TCP扫描可能会留下日志记录 -sC 使用默认脚本(在-A模式下不需要) -p1-xxx 扫描端口号 -p- ==>等价于 -p1-65535 ...
- Flutter开发技巧集锦
flutter中单例的写法 class AccountManager { factory AccountManager() => _instance ??= AccountManager._() ...
- 通过一个非常简单的SSM项目来将SpringMVC配置整理清晰。
所有的文件在Git上面都能找到,由于把代码搞上来看的很不舒服,结构不清晰. 第一步:确定环境 IDEA MySQL 5.7.19 Tomcat 9 Maven 3.6 第二步:创建数据库 参考GIT上 ...
- python异步正则字符串替换,asyncio异步正则字符串替换re
自然语言处理经常使用re正则模块进行字符串替换,但是文本数量特别大的时候,需要跑很久,这就需要使用asyncio异步加速处理 import pandas as pd import re import ...
- 为什么Spring仍然会是云原生时代最佳平台之一?
简介: 基于Java语言的Spring生态,还能否适应新的开发方式,比如Cloud Native.Serverless.Faas等,它还会是云原生时代的最佳平台的选择吗?本文将从5个角度来为你分析一下 ...
- 在 Dubbo3.0 上服务治理的实践
简介: Dubbo 3.0 是在云原生背景下诞生的,使用 Dubbo 构建的微服务遵循云原生思想,能更好的复用底层云原生基础设施.贴合云原生微服务架构. Dubbo3.0 介绍 作者 | 十眠 自从 ...
- [FAQ] Error 1142: INDEX command denied to user
MySQL 用户没有某个命令权限时提示的错误.具体这里提示的是没有 index 命令权限. 把某库的所有表的 index 命令授权给用户即可: grant index on xxdb.* to 'xx ...
- [Gin] 运行模式检测和设置 (mode.go)
// 设置方式 gin.SetMode(gin.ReleaseMode) // 检测方式 if gin.Mode() == gin.DebugMode { } 更多相关信息,建议直接去看源代码. Re ...
- 七天.NET 8操作SQLite入门到实战 - (2)第七天Blazor班级管理页面编写和接口对接
前言 上一章节我们引入BootstrapBlazor UI组件完成了EasySQLite后台界面的基本架子的搭建,本章节的主要内容是Blazor班级管理页面编写和接口对接. 七天.NET 8 操作 S ...
- 鸿蒙HarmonyOS实战-ArkUI事件(触屏事件)
前言 触屏事件是指通过触摸屏幕来进行操作和交互的事件.常见的触屏事件包括点击(tap).双击(double tap).长按(long press).滑动(swipe).拖动(drag)等.触屏事件通常 ...