ccpc 2016 合肥站 (5道题)
来源:互联网 发布:星空倒影 知乎 编辑:程序博客网 时间:2024/04/29 18:50
5961.传递 (思维题)
http://acm.hdu.edu.cn/showproblem.php?pid=5961
题目大意:
给你两个有向图,问你这两个图是否都是传递的。
一个有向图是传递的,当且仅当图中任意三点a,b,c,若存在边a->b,b->c则必存在边a->c.
题目分析:
bfs图,若存在一个点的深度>=3,则不是。
为什么呢?道理很简单,如果bfs序列中有c点的深度是3,设父亲是b,爷爷是a,则一定存在a->b,b->c,而不存在a->c,否则c的深度就是2了
#include <bits/stdc++.h>using namespace std;#define RE(x) freopen(x,"r",stdin)#define WR(x) freopen(x,"w",stdout)typedef long long ll;vector<int> g1[2222],g2[2222];bool vis1[2222],vis2[2222];int T,n;char c;bool bfs(int u,vector<int> g[]) { bool* vis; if(g==g1) vis=vis1; else vis=vis2; queue<int> q; int d[2222]; q.push(u); vis[u]=true; d[u]=1; while(!q.empty()) { int v=q.front(); q.pop(); if(d[v]==3) return false; for(int i=0;i<g[v].size();i++) { int next=g[v][i]; if(!vis[next]) { d[next]=d[v]+1; vis[next]=true; q.push(next); } } } return true;}int main() { // RE("in.txt"); // WR("out.txt"); scanf("%d",&T); while(T--) { scanf("%d",&n); for(int i=1;i<=n;i++) { g1[i].clear(); g2[i].clear(); vis1[i]=vis2[i]=false; } getchar(); for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++) { scanf("%c",&c); if(c=='P') g1[i].push_back(j); else if(c=='Q') g2[i].push_back(j); } getchar(); } bool flag1=true,flag2=true; for(int i=1;i<=n;i++) { if(!vis1[i]) flag1=bfs(i,g1); if(!flag1) break; if(!vis2[i]) flag2=bfs(i,g2); if(!flag2) break; } if(!flag1 || !flag2) cout<<"N"<<endl; else cout<<"T"<<endl; }}
5963.朋友(博弈,思维题)
http://acm.hdu.edu.cn/showproblem.php?pid=5963
题目大意:
懒得抄了
题目分析:
观察游戏规则,我们发现了规律,如果根节点到一个孩子的边是1,那么不管后面的边是什么样的,把这条链变成全0需要的操作次数就是奇数次,否则是偶数次,是0反之。
直观上是这么证明的:(有点像数学归纳法,我也不知道是不是)
* 如果这条链上只有1,那么需要1次是奇数。
* 假设对序列
对于从0开始的链亦同理。
那么得出结论:如果根节点下面的孩子节点的边中,1的个数是奇数,则需要奇数次操作变成全0,即女生胜,否则男生胜。
剩下的就是维护树边就可以了,首先以1为根,dfs/bfs确定深度和父节点,然后深度大的往深度小的父亲找,并更新权值直到相遇即可。
至于数据结构,这里用的是前向星,顺便学习了一下这种数据结构。(其实邻接表也同理,需要在深搜的时候记下每个点的父节点在邻接表中的序号,学习了不熟悉的数据结构,就懒得写了)
关于前向星,请阅读这篇文章:http://blog.csdn.net/acdreamers/article/details/16902023 ,我就不重复了。
我记得最大流算法里面的图也是用前向星做的,之前没意识到直接套模板了。。。现在好好学习一下。
关于树中边的信息维护还有一种更加高级的算法叫树链剖分,本人比较菜暂时还不懂这个。。。。
相关博文放在这,有机会看看:
树链剖分原理
树链剖分(一)(#请配合树链剖分(二)以及线段树一起食用-_-)
树链剖分(二)
树链剖分(三)(除了道馆之战——暂时可以告一段落了)
#include <bits/stdc++.h>using namespace std;typedef long long ll;int T,n,m;struct node{ int to,next,w;}edge[80005];int head[40005],cnt,op;int dep[40005],e[40005],father[40005];//dep表示第i个点的深度,father表示第i个点的父节点,e[i]表示终点为i的边的序号void addedge(int u,int v,int w) { edge[cnt].to=v; edge[cnt].w=w; edge[cnt].next=head[u]; head[u]=cnt++;}void dfs(int u,int f,int d) { //u点,父节点是f,深度是d dep[u]=d; father[u]=f; for(int i=head[u];i!=-1;i=edge[i].next) { int v=edge[i].to; if(v!=f) { e[v]=i; dfs(v,u,d+1); } }}int main(){ scanf("%d",&T); while(T--) { scanf("%d %d",&n,&m); memset(head,-1,sizeof(head)); cnt=0; for(int i=1;i<n;i++) { int u,v,w; scanf("%d %d %d",&u,&v,&w); addedge(u,v,w); addedge(v,u,w); } dfs(1,0,1); for(int i=0;i<m;i++) { scanf("%d",&op); if(op) { int x,y,z; scanf("%d %d %d",&x,&y,&z); while(x!=y) { if(dep[x]<dep[y]) swap(x,y); int id=e[x]; edge[id].w=edge[id^1].w=z; x=father[x]; } } else { int x; scanf("%d",&x); int ans=0; for(int i=head[x];i!=-1;i=edge[i].next) { ans+=edge[i].w; } if(ans&1) printf("Girls win!\n"); else printf("Boys win!\n"); } } } return 0;}
5965.扫雷(枚举)
http://acm.hdu.edu.cn/showproblem.php?pid=5965
题目大意:
有一个3*n的扫雷棋盘,中间那行都已经给出了数,问有多少种埋雷方案?
题目分析:
枚举第一列有几个雷,则其他列有几个雷都是确定的,有0个雷或者2个雷方法数均为1,1个雷为2,连乘即可。
#include<bits/stdc++.h>using namespace std;typedef long long ll;const int maxn=11111;const int mod=1e8+7;char s[maxn];int num[maxn],dp[maxn];int main(){ int T; scanf("%d",&T); while(T--) { scanf("%s",s); int n=strlen(s); for(int i=0;i<n;i++) num[i+1]=s[i]-'0'; memset(dp,0,sizeof(dp)); ll ans=0; for(int i=0;i<=num[1];i++) { dp[1]=i; if(i>2)break; int j; for(j=2;j<=n;j++) { int k=num[j-1]-dp[j-1]-dp[j-2]; if(k>2||k<0) break; dp[j]=k; } if(j<=n)continue; if(dp[n-1]+dp[n]!=num[n])continue; ll res=1; for(int i=1;i<=n;i++) { if(dp[i]==0||dp[i]==2) res*=1; else res*=2; res%=mod; } ans+=res; ans%=mod; } printf("%d\n",ans); } return 0;}
5968.异或密码(水)
http://acm.hdu.edu.cn/showproblem.php?pid=5968
题目大意:
给你一个序列,求出每个子序列异或的结果,找到所有的结果中与xi之差的绝对值最小的一个,并输出相应子序列的长度。如果有多个答案,则输出最长的。
题目分析:
因为只有100个用例,每个用例的长度只有100,所以暴力搞的复杂度也不过是
#include <bits/stdc++.h>using namespace std;#define RE(x) freopen(x,"r",stdin)#define WR(x) freopen(x,"w",stdout)typedef long long ll;int T,n,m;int x[105][105];int a[105];void pre() { x[0][0]=a[0]; for(int i=1;i<n;i++) x[0][i]=x[0][i-1]^a[i]; for(int i=1;i<n;i++) { for(int j=i;j<n;j++) { x[i][j]=x[0][j]^x[0][i-1]; } }}int main() { scanf("%d",&T); while (T--) { scanf("%d",&n); for(int i=0;i<n;i++) { scanf("%d",&a[i]); } pre(); scanf("%d",&m); while(m--) { int q; scanf("%d",&q); int b=123456,l=-1; for(int i=0;i<n;i++) { for(int j=i;j<n;j++) { if(abs(x[i][j]-q)<b) { b=abs(x[i][j]-q); l=j-i+1; } else if(abs(x[i][j]-q)==b) { if(j-i+1>l) l=j-i+1; } } } printf("%d\n", l); } printf("\n"); }}
5969.最大的位或(位运算)
http://acm.hdu.edu.cn/showproblem.php?pid=5969
题目大意:
给两个数l和r,从[l,r]中取两个数x,y,使得x|y最大,输出这个最大值。
题目分析:
其实这题挺符合leetcode 的画风,应该有可能出现在求职笔试面试中,引起重视!!
很明显r的二进制位大于等于l的,统计r有多少位,然后开始下手。
从高位往低位看,如果l和r对应位是相等的,则这一位是什么答案就加上什么,例:
1 0 1 0 ….
1 0 1 0 ….
很明显任意[l,r]之间的数的最高位都是这些。
那么如果遇到不同的位,例:
… 0 …
… 1 …
则x中可以取到..011111...
,y中必可以取到...100000..
,因为这两个数一定存在~~
所以只要遇到l和r出现不同数位,则答案加上...11111..
即可。
#include <bits/stdc++.h>using namespace std;#define RE(x) freopen(x,"r",stdin)#define WR(x) freopen(x,"w",stdout)typedef long long ll;ll l,r;int T;int get(ll r) { return (r<2)?1:get(r/2)+1;}int main(){ scanf("%d",&T); while(T--) { scanf("%I64d %I64d",&l,&r); ll ans=0; int i=get(r)-1; while(i>=0) { if((r&(1LL<<i))==(l&(1LL<<i))) ans+=r&(1LL<<i); else break; i--; } ans+=(1LL<<(1+i))-1; cout<<ans<<endl; }}
感觉我在赛场上最多只能做出3题。。。据说4题才有牌,但我感觉公司笔试题难度不输给这些题的前半部分~,是不是我也要失业了。。。【柯南思考状~】
- ccpc 2016 合肥站 (5道题)
- 2016CCPC合肥站流水账
- 2016ccpc合肥站小记
- 2016 CCPC 合肥站游记
- 2016年CCPC合肥站
- 2016ccpc合肥站赛后总结
- 2016ccpc 合肥站hdu 5965 扫雷
- hdu 5963 朋友 ccpc 2016 合肥站
- hdu 5965 扫雷 ccpc 2016 合肥站
- hdu 5961 传递 ccpc 2016 合肥站
- 2016 CCPC 合肥站 解题报告
- ccpc 合肥站记
- 2016CCPC合肥总结
- CCPC 合肥站 打铁记
- 2016CCPC合肥赛区总结
- 2016 ACM-CCPC 合肥总结
- 2016 ccpc 合肥 赛后感
- 2016 ccpc 合肥 HDU5965 扫雷
- UML——用例图
- Geo server 发布shp格式地图
- WPF处理窗体的最小化事件及恢复正常窗体事件
- 用数学方法解约瑟夫环
- nodejs操作mongodb数据库(mongoose)
- ccpc 2016 合肥站 (5道题)
- Vue 固定头 固定列 点击表头可排序 表格组件
- 从1到n的n个整数中1出现的次数
- react-native 运行报Could not get BatchedBridge, make sure your bundle is packaged correctly 错误
- 关于ODBC和JDBC连接actian vortex数据库的bug报告
- Android中JNI开发的相关研究
- 浮点数转化为二进制整型
- JAVA从零单排-----继承、封装和多态详解
- Yii2.0如何建立公共方法