NOIp/CSP-S 历年真题混做
不希望考的太差,>-< 抽出时间狠狠的练
预计做到复赛前一周,然后开始复习板子
排除一些原来已经刷过去了的题,写一些简单的题解找找感觉。
P1082 [NOIP2012 提高组] 同余方程
有了 这个东西,
一眼就能看出来数论题。
考虑拓展欧几里得求一下逆元。
由于在最后得结果时有可能会得到负数,因此考虑输出的时候用一下 (x % b + b) % b
这个语句来处理一下非负。
但是板子写的时候别写错了,
int exgcd(long long a, long long b, long long& x, long long& y)
这个地方,要注意下。
核心码
点击查看代码
int gcd(int a, int b,int &x,int &y) {
if (b == 0) {
x = 1, y = 0;
return a;
}
int ans = gcd(b, a % b, x, y);
int temp = x;
x = y;
y = temp - a / b * y;
return ans;
}
P1083 [NOIP2012 提高组] 借教室
看到题面没什么思路,
暴力一下再加一些前缀和优化应该可以。
复杂度: 大致是可以过去的。
就没考虑线段树的做法。
这个代码就不放了,毕竟放了啥也复习不了(
考场上真出现这种题我可能还真不敢写呢(,问就是因为害怕出题人放下的坑
P1081 [NOIP2012 提高组] 开车旅行
这个的预处理好难写啊。。。果真第3题还是做不出来吗。
想到了一个暴力的解法,但是显然不是正解,而且还有没考虑到的地方
所以仍旧不能打满。
正解我也不太会写,看题解区的题解写的要 dp 加一个挺难的预处理的。
不会。
看来还是因为有好多知识点不会就好多做不出来。
得把 multiset
赶紧学学。
看标程果然是很长的,
贴上了以后自己研究去吧,就当个拓展好了。
第 1 篇题解上写的代码
#include<iostream>
#include<cstdio>
#include<cmath>
#include<set>
using namespace std;
const int N=1e5+200,INF=2e9;
struct City
{
int id,al;//identifier,altitude
friend bool operator < (City a,City b)
{
return a.al<b.al;
}
};
int n,m,x0,la,lb,ansid;
int h[N],s[N],x[N];
int f[20][N][5],da[20][N][5],db[20][N][5];
double ans=INF*1.0;
multiset<City> q;
void calc(int S,int X)
{
int p=S;
la=0,lb=0;
for(int i=18;i>=0;i--)
if(f[i][p][0] && la+lb+da[i][p][0]+db[i][p][0]<=X)
{
la+=da[i][p][0];
lb+=db[i][p][0];
p=f[i][p][0];
}
}
void pre()
{
h[0]=INF,h[n+1]=-INF;
City st;//start
st.id=0,st.al=INF;
q.insert(st),q.insert(st);
st.id=n+1,st.al=-INF;
q.insert(st),q.insert(st);
for(int i=n;i;i--)
{
int ga,gb;
City now;
now.id=i,now.al=h[i];
q.insert(now);
set<City>::iterator p=q.lower_bound(now);
p--;
int lt=(*p).id,lh=(*p).al;//last
p++,p++;
int ne=(*p).id,nh=(*p).al;//next
p--;
if(abs(nh-h[i])>=abs(h[i]-lh))
{
gb=lt;
p--,p--;
if(abs(nh-h[i])>=abs(h[i]-(*p).al))
ga=(*p).id;
else
ga=ne;
}
else
{
gb=ne;
p++,p++;
if(abs((*p).al-h[i])>=abs(h[i]-lh))
ga=lt;
else
ga=(*p).id;
}//2、预处理
f[0][i][0]=ga,f[0][i][1]=gb;
da[0][i][0]=abs(h[i]-h[ga]);
db[0][i][1]=abs(h[i]-h[gb]);//3、DP初值
}
for(int i=1;i<=18;i++)
for(int j=1;j<=n;j++)
for(int k=0;k<2;k++)
if(i==1)
{
f[1][j][k]=f[0][f[0][j][k]][1-k];
da[1][j][k]=da[0][j][k]+da[0][f[0][j][k]][1-k];
db[1][j][k]=db[0][j][k]+db[0][f[0][j][k]][1-k];
}
else
{
f[i][j][k]=f[i-1][f[i-1][j][k]][k];
da[i][j][k]=da[i-1][j][k]+da[i-1][f[i-1][j][k]][k];
db[i][j][k]=db[i-1][j][k]+db[i-1][f[i-1][j][k]][k];
}//3、倍增优化DP
}
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
scanf("%d",&h[i]);
cin>>x0>>m;
for(int i=1;i<=m;i++)
scanf("%d%d",&s[i],&x[i]);//1、输入
pre();
for(int i=1;i<=n;i++)
{
calc(i,x0);
double nowans=(double)la/(double)lb;
if(nowans<ans)
{
ans=nowans;
ansid=i;
}
else
if(nowans==ans && h[ansid]<h[i])
ansid=i;
}
cout<<ansid<<endl;//4、求解问题1
for(int i=1;i<=m;i++)
{
calc(s[i],x[i]);
printf("%d %d\n",la,lb);
}//5、求解问题2
return 0;
}
来自第1篇题解。
2012年 tg 组题目总结
还是很菜,别指望今年 7 级了,
还是原来学的太少了,
不过好的是暴力还不错
还是要多学点知识的,但是总体感觉做的不错,,,自我感觉永远不错。
P1966 [NOIP2013 提高组] 火柴排队
看到题目就很容易想到树状数组。
刚好复习一下也挺好(,虽然一开始想不太起来咋写
两个序列的距离:,因此,尽量让 小
然后求一下就行了
树状数组的话要离散化,
不过我是用排序做的
挂一下树状数组的板子复习吧:
单点修改
int tree[100001];
inline void update(int i, int x)
{
for (int pos = i; pos < 100001; pos += lowbit(pos))
tree[pos] += x;
}
求前n项和
inline int query(int n)
{
int ans = 0;
for (int pos = n; pos; pos -= lowbit(pos))
ans += tree[pos];
return ans;
}
区间查询
inline int query(int a, int b)
{
return query(b) - query(a - 1);
}
P1967 [NOIP2013 提高组] 货车运输
感觉是最短路,希望能想到正解
但是却感觉想写却不知道咋写。。。
寄了。
发现这个用并查集也挺难弄得。
果真这种离谱结合还是不会吗。。。
P1970 [NOIP2013 提高组] 花匠
但是这个好像还挺简单的,因为题目里面说 的时候最多一个满足。
但是我还是提交了好几次还不行。
在此处刑:由于 zzds 出于想走捷径的心理而看了一眼题目算法标签。
严重违背了当初的承诺。
并且在最后为了通过此题然后在调不出来时在最后加了一个cout<<ans - 1<<endl;
考场上是觉得不允许的。
第一次提交只有 50 分,没打满,惭愧。
2013年 tg 组题目总结
除了那个处刑外,感觉自己也真的是太想要自己能配得上蓝钩了然后就很急躁。
看着别人做出来自己做不出来就想走捷径比如输出答案减 1。
这种事绝对不允许。
而且经常就是想不出来正解怎么做
然后就自暴自弃打暴力去了
有的时候开题数据范围不看,最后提交时候才看,看完之后又不去再测一遍。
不允许。
本文作者:zsdqwq
本文链接:https://www.cnblogs.com/wo-de-bo-ke-wo-zuo-zhu/p/16598502.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步