10.22考试总结
来源:互联网 发布:cdma是什么网络模式 编辑:程序博客网 时间:2024/06/06 23:50
先说今天考试比较水很多dalao都Ak了,然后我是真的很想抽自己,下面请看;
1.斐波那契数
题目大意:给一个数,判断它是不是两个斐波那契数的乘机(n<=100000000);
感想:很容易看出来f[45],就超1e9了,然后n方枚举就ok了,我日常卡第一题,花了一个半小时,硬是找了个规律,写了个logn的东西,首先可以二分求出f[l]<=n<=f[r],然后你可以发现它们可以是和f[1]的乘积,而这中间的斐波那契数的乘积都一定是由f(l+2-i)*f(i)得来的,这样在(l+2)/2到l枚举,因为它不超过45,所以一半大概是20几,差不多也是log级别的,所以玄学的花了1个半小时写出来,我也是醉了。
# include <iostream># include <cstdio># include <cstring># include <algorithm># include <cmath># include <list>using namespace std;typedef long long ll;ll read(){ll f=1,i=0;char ch=getchar();while(ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=getchar();}while(ch>='0'&&ch<='9'){i=(i<<3)+(i<<1)+ch-'0';ch=getchar();}return f*i;}ll f[1000],x;int main(){f[0]=0;f[1]=1;for(int i=2;i<=100;++i) f[i]=f[i-1]+f[i-2];int t=read();while(t--){x=read();int l=1,r=50;while(l<=r){int mid=l+r>>1;if(f[mid]<=x) l=mid+1;else r=mid-1;}int L,R,flag=0;if(x==f[l]||x==f[r]) flag=1;R=r-1;if((2+r)&1) L=(2+r)/2+1;else L=(2+r)/2;for(int i=L;i<=R;++i) if(f[i]*f[r+2-i]==x) flag=1;if(flag) {puts("Yes");}else puts("No");}}2.一样远
题目大意:给一棵树,在给两个点a,b,求树上到它们距离相等的点有多少个。
感想:因为第一题的智障,我还剩两个小时刚后两道题,然后这一道题花了50分钟写完,lca+倍增嘛,过了样例以及手造的几组大样例,感觉很稳,因为时间不够也懒得打对拍了,于是成功wa的只剩十分。正解:求lca,然后倍增找到中点,中点中含有a,b两点的子树上的点都不能选于是减去,剩下的就是答案,注意lcd就是中点的时候要特判,而且是有可能两个点一个在上一个在下,或是两个都在下,别问我怎么知道的,说来都是qaq。
# include <iostream># include <cstdio># include <cstring># include <algorithm># include <cmath># include <list>using namespace std;typedef long long ll;int read(){int f=1,i=0;char ch=getchar();while(ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=getchar();}while(ch>='0'&&ch<='9'){i=(i<<3)+(i<<1)+ch-'0';ch=getchar();}return f*i;}const int N=100005;struct node{int v;node *next;}E[N<<2],*first[N],*cnt=E;int n,m,x,y,z,q,lenth,son;int dis[N],dep[N],fa[N][20],size[N];bool vis[N]={false};inline void AddEdge(int x,int y){node *p=++cnt;p->next=first[x];first[x]=p;p->v=y;}inline void DFS(int u){vis[u]=true;size[u]=1;for(node *p=first[u];p;p=p->next){if(!vis[p->v]){dis[p->v]=dis[u]+1;dep[p->v]=dep[u]+1;fa[p->v][0]=u;DFS(p->v);size[u]+=size[p->v];}}}inline void pre(){for(int j=1;j<=17;++j) for(int i=1;i<=n;++i) if(fa[i][j-1]) fa[i][j]=fa[fa[i][j-1]][j-1];}int LCA(int x,int y){int len=dep[x]-dep[y];for(int i=17;i>=0;--i){if(len>=(1<<i)){len-=(1<<i);x=fa[x][i];}}if(x==y) return x;for(int i=17;i>=0;--i){if(fa[x][i]!=fa[y][i]){x=fa[x][i];y=fa[y][i];}}return fa[x][0];}int update(int len,int x){for(int i=17;i>=0;--i){if(len>=(1<<i)){len-=(1<<i);x=fa[x][i];}}return x;}int main(){n=read();for(int i=1;i<n;++i){x=read(),y=read();AddEdge(x,y),AddEdge(y,x);}DFS(1);pre();m=read();while(m--){x=read(),y=read();if(x==y){printf("%d\n",n);continue;}if(dep[x]<dep[y])swap(x,y);int lca=LCA(x,y);son=0;lenth=dis[x]+dis[y]-2*dis[lca];if(lenth&1) printf("0\n");else{lenth>>=1;int fx,fy;fx=update(lenth-1,x);fy=update(lenth-1,y);if(dep[x]-dep[lca]==lenth) {cout<<n-size[fx]-size[fy]<<endl;continue;}cout<<size[fa[fx][0]]-size[fx]<<endl;}}}3.拆网线
题目大意:给一棵树,给一个点数k,要求保证k点中一个点至少与另一个点有一条边,求最少保留几条边;
感想:因为前两道题的智障,于是想了会,发现就是一个贪心嘛,两两配对下来一定最优,于是拓扑排序,每次选入度最小的与它对面的点匹配,走一遍就行了,于是复杂度o(n),输出时如果要求的点数大于两个点的对数(num)乘2,则输出k-num*2+num,若大于则输出(k+1)/2,而我智障的直接输出了num,我可能是吃了假药吧。
# include <iostream># include <cstdio># include <cstring># include <algorithm># include <cmath># include <list># include <queue>using namespace std;typedef long long ll;int read(){int f=1,i=0;char ch=getchar();while(ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=getchar();}while(ch>='0'&&ch<='9'){i=(i<<3)+(i<<1)+ch-'0';ch=getchar();}return f*i;}const int N=100005;struct node{int u,v,next;}E[N<<2];int t,n,m,x,y,k,cnt,r[N],mark[N],first[N];inline void initial(){ cnt=0; memset(mark,0,sizeof(mark)); memset(r,0,sizeof(r)); memset(first,0,sizeof(first)); memset(E,0,sizeof(E));}inline void AddEdge(int x,int y){ E[++cnt].next=first[x]; first[x]=cnt; E[cnt].v=y; r[x]++,r[y]++;}int main(){ t=read();while(t--){ initial(); n=read(),k=read(); for(int i=1;i<n;++i) { x=read(); AddEdge(x,i+1); AddEdge(i+1,x); } queue<int>q; for(int i=1;i<=n;++i) if(r[i]==2) q.push(i); while(!q.empty()) { int now=q.front();q.pop(); for(int i=first[now];i;i=E[i].next) { int v=E[i].v;if(!mark[now]&&!mark[v]) mark[now]=1,mark[v]=2; r[v]-=2;if(r[v]==2) q.push(v); } } int num=0; for(int i=1;i<=n;++i) if(mark[i]==1) num++; if(k<=num*2) printf("%d\n",(k+1)/2); else printf("%d\n",k-num*2+num);}}
总结:t1日常被卡,我真的是个妖怪,要注意别想太复杂了,毕竟是t1,然后只要t1半小时内写完,后面就有时间打个对拍,应该就会很稳了。
- 10.22考试总结
- 考试总结
- 考试总结
- 考试总结
- 考试总结
- 考试总结
- 考试总结
- 考试总结
- 考试总结
- 考试总结
- 考试总结
- 考试总结
- 考试总结
- 考试总结
- 考试总结
- 考试总结
- 考试总结
- 考试总结
- 唠唠(信息熵)一大家子的事
- 【Android】关于selinux等引起的权限问题
- size(A,1)
- svg文件报错
- 制作ZedBoard-linaro-desktop-ubuntu全过程之编译u-boot
- 10.22考试总结
- 视频编码原理简介
- idea下项目关联成maven
- BOM
- python: sort 与 sorted 区别
- dubbo.xml上报异常解决方案
- ssh框架环境搭建
- Django根据现有数据库建立/更新model
- [DeeplearningAI笔记]改善深层神经网络_深度学习的实用层面1.10_1.12/梯度消失/梯度爆炸/权重初始化