10.25.2017 考试总结与解题报告
来源:互联网 发布:2016淘宝年会 马云 编辑:程序博客网 时间:2024/06/07 12:29
这次考试题目难度不是很大,但考得并不是很好,主要原因有仨:
①性情浮躁
这次考试第一题我是完全有能力A的,但是就是因为一个to数组严格代表什么,该运用到那些方面去没有仔细分析,过了样例就没管了,结果到考试前五分钟拍出n多错误,那时已经没时间调试了,其实那时候还可以用几十秒把我的暴力对拍程序改改文件名交上去,暴力分有五十分啊ヽ(ˋДˊ)ノ那也不至于这题爆零(我是唯一这题爆零的,大家都起码交了一个暴力50分),还有,现成的暴力对拍程序放在那,我只要改一改文件名就行了啊(这可能是OI史上唯一一次暴力对拍程序比本体分高的了)
② 不注意数据范围
这次考试第二题的俩输入变量是1e12的范围,由于一推出公式就得意忘形了,只开了个int,long long都没开,结果丢了70分
③缺乏缜密思考的能力
其实我在做第三题时,思想与正解有很长一段的交集,但最终没有继续,原因是因为不敢用这种感觉上比较偏的方法,说明我的思考证明能力以及自信心都有所不足
综合这次考试反应出了我的很多弊病,我应该逐步改正,防止这成为我NOIP无法上一等的原因
下面附上这次考试的解题报告
Task pudding
【题目描述】
现在有 n 个布丁排成一排,每个布丁都有一个正整数颜色。
有 m 个操作:
第一种操作 1 x y 将所有颜色为 x 改为颜色 y。
第二种操作 2
询问当前有多少段颜色。
【输入数据】
第一行两个正整数 n,m。
下面一行,n 个正整数,表示一排的布丁。
下面 m 行,每行为一个操作。
【输出数据】
输出每组询问的答案。
【输入样例】
4 3
1 2 2 1
2
1 2 1
2
【输出样例】
3
1
【数据约定】
50%
n,m <= 2000
100% n,m <= 100000,颜色均不超过 10^6
题目概要
这题原型其实就是HNOI-2009的梦幻布丁,题意是给出一条序列,每次询问其中有多少段或将序列中所有的A变为B
思路
50分解法
50分解法非常好想 ,其实就是暴力更改查询,然而这小学生都该拿的分就我没拿
对于50分暴力的优化
目前我能想到的优化只有两个:
一是线段树解法,就像维护区间最长连续串儿一样维护
二是用链表,每次保证遍历的每一次都不会浪费,最后把俩链连起来就行了
但是法一不推荐,代码难打复杂度高
100分解法
为什么要写“对于50分暴力的优化”,还是自有它的原因,就像NOIP2016天天爱跑步一样,都是由部分分“进化”而得正解
这题也是一样,楼上法二只要优化一点点便可AC
首先让我们分析一下为什么法二会TLE,对于最坏复杂度(不管是一名OIER 还是cy的学生 都要感受数据的恶意,不能乐观,往往正解是保证最坏复杂度也能A的),每一次修改最坏
那么我们应该加一些优化,降复杂度为
这题我们分析一下,
分析得出最坏复杂度发生在将长度为
我们引进启发式合并的概念
把小集合往大集合上合并称为启发式合并,这样的预估复杂度为
O(log2n)
复杂度证明: 一个元素从一个集合被加入另一个集合时, 所在集合的规模至少扩大一倍. 如果没有分离操作且元素数目有限, 合并的次数是O(log2n) 的.
发现这样做好像复杂度变为
等等,突然间发现对拍停住了,看看数据,发现有一种情况会挂:
当我们把1变为3 , 2变为3时,由于3的个数是零,所以把3连到了1,又把3连到了2,但其实3和2应该合并的
万能的神奇海螺告诉我们,可以用一个to数组记录每个颜色实际表示的啥呀,比如
然后就可以真正地AC了
蒟蒻瑟瑟发抖的代码
#include<bits/stdc++.h>#define rg registerusing namespace std;template <typename _Tp> inline void read(_Tp &x){char c11=getchar();x=0; while(c11<'0'||c11>'9')c11=getchar();while(c11>='0'&&c11<='9'){x=x*10+c11-'0';c11=getchar();}}const int maxn=2000005,maxm=4000001;int n,m,ans=0;int P,p,x,y;int a[maxn],to[maxm],b[maxn];int head[maxm],nt[maxn];int r[maxn],tot[maxm];void init();void work(){ for(int t=1;t<=m;++t){ read(P); if(P==1){ read(x);read(y);// x=b[lower_bound(b+1,b+n+1,x)-b];// y=b[lower_bound(b+1,b+n+1,y)-b]; if(to[x]==to[y])continue; //注意以下代码都是带to数组的,应为to的下标已无任何意义 if(tot[to[x]]>tot[to[y]])swap(to[x],to[y]); //启发式合并的神来之笔 for(int i=head[to[x]];i;i=r[i]) //动态维护ans ans-=(a[i]!=a[i-1])+(a[i]!=a[i+1]); //左右相同减一或二 for(int i=head[to[x]];i;i=r[i])a[i]=to[y]; p=0; for(int i=head[to[x]];i;i=r[i]) ans+=(a[i]!=a[i-1])+(a[i]!=a[i+1]),p=i; //更改后与其不同,加一 if(p) r[p]=head[to[y]],head[to[y]]=head[to[x]]; //这三行都是合并操作 head[to[x]]=0; tot[to[y]]+=tot[to[x]],tot[to[x]]=0; } else printf("%d\n",ans); }}int main(){// freopen("pudding.in","r",stdin);// freopen("pudding.out","w",stdout); init(); work(); return 0;}void init(){ read(n);read(m); for(rg int i=1;i<=maxm;++i)to[i]=i; for(rg int i=1;i<=n;++i) read(a[i]);//b[i]=a[i];// sort(b+1,b+n+1);int kl=unique(b+1,b+n+1)-b; //本想离散化的// for(rg int i=1;i<=n;++i)a[i]=b[lower_bound(b+1,b+n+1,a[i])-b]; for(rg int i=1;i<=n;++i){ ans+=(a[i]!=a[i-1]); r[i]=head[a[i]]; head[a[i]]=i; ++tot[a[i]]; }}
Task prison
【题目描述】
现在有一个长度为 n 的序列,请你给它的每一个位置都染上一个 1~m 的颜色,使得至
少有一个相邻的格子颜色相同,问有多少种方案。
答案请 mod 100003。
【输入数据】
两个正整数m,n。
【输出数据】
输出方案数。
【输入样例】
2 3
【输出样例】
6
【数据约定】
30%:n <= 50,m <= 1000
100%:n <= 10^12,m <= 10^8。
题目还需要概要吗?
以HNOI2008越狱为原型
思路
10分解法
直接深搜
30分解法
由我们丰富的数学知识可知总共有
100分解法
用上快速幂,还有……
开long long
开了long long的代码
这里写代码片#include<bits/stdc++.h>using namespace std;const long long mod=100003;long long n,m;long long qpow(long long A,long long B){ long long ans=1; while(B){ if(B&1)ans=(ans*A)%mod; //多mod是好事 A=A*A%mod; B>>=1; } return ans;}void work(){ long long fir=qpow(m,n); long long sec=(m*qpow(m-1,n-1))%mod; while(fir<sec)fir+=mod; printf("%lld\n",(fir-sec)%mod); return ;}int main(){ freopen("prison.in","r",stdin); freopen("prison.out","w",stdout); scanf("%lld %lld",&m,&n); work(); return 0;}
Task SPFA
【题目描述】
给你一张含有 n 个点 m 条边的联通无向图,记录 1 号点到每个点的最短路长度,询问去掉与 i 号相邻的所有边后,1 号点到多少个点的最短路长度改变,若不连通则也视为改变。
【输入数据】
第一行两个正整数 n,m,
接下来 m 行,每行三个正整数数 i,j,k,表示一条边< i , j >,长度为 k。
【输出数据】
N 行,第 i 行表示去掉与 i 号相邻的所有边后,1 号点到多少个点的最短路长度改变。
【输入样例】
2 1
1 2 1
【输出样例】
1
1
【数据约定】
30% n <= 100,m <= 300
100% n <= 5000,m <= 20000,边权均为不超过 100 的正整数。
题目概要
求对于每一个点
思路
30分解法
不断求最短路,看看有多少个点最短距离改变
100分解法
删去那些不是任何最短路上的点,再枚举每一个点,将其入队,将其所有指向点入读减一,入度为零的点入队,最后入队数量就是ans
Atention:当删去的点为一时输出ans-1
因为删掉点1后,1到1的距离从0变成了0
代码
#include<bits/stdc++.h>using namespace std;#define rg register#define cl(x) memset(x,0,sizeof(x))#define cl1(x) memset(x,-1,sizeof(x))template <typename _Tp> inline void read(_Tp &x){char c11=getchar();x=0;while(c11<'0'||c11>'9')c11=getchar();while(c11>='0'&&c11<='9'){x=x*10+c11-'0';c11=getchar();}}const int maxn=5050,maxm=20020;int n,m;struct node {int v,w,nxt;} a[maxm<<1];int head[maxn],p=0;int dis[maxn];int tot[maxn],oto[maxn];struct node1 {int v,w,nxt;} b[maxm<<1];int head1[maxn],p1=0;void init();inline void add(int,int,int);inline void add1(int,int,int);void spfa(){ queue <int> q; q.push(1); cl1(dis); dis[1]=0; while(!q.empty()){ int x=q.front(); q.pop(); for(rg int i=head[x];i;i=a[i].nxt)if(dis[a[i].v]==-1||dis[a[i].v]>dis[x]+a[i].w)dis[a[i].v]=dis[x]+a[i].w,q.push(a[i].v); } return ;}void ex(){ //重新构图函数 cl(head1);cl(tot); for(rg int i=1;i<=n;i++) for(rg int j=head[i];j;j=a[j].nxt) if(dis[i]+a[j].w==dis[a[j].v]) //若这条边是最短路一部分 add1(i,a[j].v,a[j].w);}void work(){ //开始队列操作 for(rg int i=1;i<=n;i++){ for(rg int j=1;j<=n;j++)oto[j]=tot[j]; queue <int> q; q.push(i); int ans=0; while(!q.empty()){ int x=q.front(); q.pop();++ans; for(rg int j=head1[x];j;j=b[j].nxt){--oto[b[j].v];if(!oto[b[j].v])q.push(b[j].v);} } if(i==1)printf("%d\n",n-1); //不加全WA else printf("%d\n",ans); } return ;}int main(){ freopen("problem.in","r",stdin);freopen("problem.out","w",stdout); init(); spfa(); ex(); work(); return 0;}void init(){ read(n);read(m); int A,B,C; cl(head); for(rg int i=0;i<m;++i){ read(A);read(B);read(C); add(A,B,C);add(B,A,C); } return ;}inline void add1(int u,int v,int w){ //重新构图 b[++p1].v=v; b[p1].w=w; b[p1].nxt=head1[u]; head1[u]=p1; tot[v]++;}inline void add(int u,int v,int w){ a[++p].v=v; a[p].w=w; a[p].nxt=head[u]; head[u]=p;}
- 10.25.2017 考试总结与解题报告
- 10.26.2017 考试总结与解题报告
- 4.3考试解题报告
- codeforces解题报告与总结
- 【Code_Vs_1014】解题报告与总结
- [USACO Jan07]考试Schul解题报告
- 16计科程设考试压轴题 解题报告
- 10月28日考试解题报告
- ZOJ3537 解题报告及总结
- 【解题报告】uva111_History Grading(历史考试, dp, LCS)
- 第九周期末(中)考试解题报告
- 1833 解题报告 就要考试了,随手更一下。
- 2016 CCF-CSP 计算机职业资格认证考试 解题报告
- 正睿OI noip2017冲刺 第一次考试T2 解题报告
- Java与C++ 解题报告
- [HNOI2012]与非 解题报告
- POJ 2017 解题报告
- WC2015总结&解题报告(伪)
- cocos2dx中lambda表达式几种用法的初步总结
- fatal: You have not concluded your merge (MERGE_HEAD exists).
- Java Security Architecture--Java安全体系技术文档翻译(一)
- 书写简介规范的代码(一)
- Python lxml模块安装教程
- 10.25.2017 考试总结与解题报告
- 关于大小端模式的说明
- web应用的组成结构
- 1002. 写出这个数 (20)
- Post 和 Get 那些事
- Android studio开发NDK环境配置
- Netty4实战第十四章:自定义编解码器
- caller和callee的区别
- seo优化很难做的原因