十四届北师大校赛题解
来源:互联网 发布:apply js 编辑:程序博客网 时间:2024/05/01 02:54
A.Check In
题目:
https://www.bnuoj.com/v3/problem_show.php?pid=51635
题意:
找到所有是bnu的账号数量
思路:
所有是bnu的账号加入map中判重就行了
代码:
//kopyh#include <bits/stdc++.h>using namespace std;int n,m,sum,res,flag;map<string,int>mp;string s,tt="bnu16-";int main(){ int i,j,k,cas,T,t,x,y,z; scanf("%d",&T); cas=0; while(T--) { scanf("%d",&n); sum=0;mp.clear(); for(i=0;i<n;i++) { cin>>s; string st = s.substr(0,6); if(st==tt&&mp[s]==0)sum++,mp[s]=1; } printf("%d\n",sum); } return 0;}
B.Squared Permutation
题目:
https://www.bnuoj.com/v3/problem_show.php?pid=51636
题意:
1~n张牌,每张牌对应的值是该牌数值对应位置的牌上的值。求区间和
思路:
区间和直接线段树搞一下,因为修改值时指向的位置改变所以本身的数值改变,而且指向这个位置的数值也会改变,所以更新时是四次更新。
代码:
//kopyh#include <bits/stdc++.h>#define INF 0x3f3f3f3f#define MOD 1000000007#define N 112345using namespace std;int n,m,sum,res,flag;int a[N],b[N];#define root 1 , n , 1#define lson l , m , rt << 1#define rson m + 1 , r , rt << 1 | 1struct node{ long long pos,val; node(long long x=0,long long y=0){pos=x,val=y;}}arr[N<<2];int tot;void pushUp(int rt){ arr[rt].val = arr[rt<<1].val+arr[rt<<1|1].val;}void updata(int l,int r,int rt,int ql,int qr,long long val){ if(l>qr||ql>r)return; if(l>=ql&&r<=qr) { arr[rt].val = val; return; } int m = (l+r)>>1; if(ql<=m)updata(lson,ql,qr,val); if(qr>m)updata(rson,ql,qr,val); pushUp(rt);}void build(int l,int r,int rt){ if(l == r) { arr[rt].val = a[a[++tot]]; arr[rt].pos = tot; return; } int m = (l+r)>>1; build(lson); build(rson); pushUp(rt);}long long query(int l,int r,int rt,int ql,int qr){ if(l>qr||ql>r) return 0; if(l>=ql&&r<=qr) return arr[rt].val; int m = (l+r)>>1; return query(lson,ql,qr)+query(rson,ql,qr);}int main(){ int i,j,k,cas,T,t,x,y,z; scanf("%d",&T); cas=0; while(T--) { scanf("%d",&n); for(i=1;i<=n;i++)scanf("%d",&a[i]); for(i=1;i<=n;i++)b[a[i]]=i; tot=0; build(root); scanf("%d",&m); while(m--) { scanf("%d%d%d",&z,&x,&y); if(z==1) { a[x]^=a[y],a[y]^=a[x],a[x]^=a[y]; b[a[x]]=x; b[a[y]]=y; updata(root,x,x,a[a[x]]); updata(root,y,y,a[a[y]]); updata(root,b[y],b[y],a[y]); updata(root,b[x],b[x],a[x]); } else printf("%lld\n",query(root,x,y)); } } return 0;}
D.Air Hockey
题目:
https://www.bnuoj.com/v3/problem_show.php?pid=51638
题意:
思路:
因为冰球速度方向一定,所以距离一定是一元二次图像,可通过三分求极值,如果极值小于0则相撞,就在极值之前的单调区间上二分0的位置就是碰撞时间,否则极值就是最近距离。
代码:
//kopyh#include <bits/stdc++.h>#define INF 0x3f3f3f3f#define MOD 1000000007#define N 1123456using namespace std;int n,m,sum,res,flag;double x[2],y[2],R[2],vx[2],vy[2];double dis(double t){ double a = x[0]+vx[0]*t; double b = y[0]+vy[0]*t; double c = x[1]+vx[1]*t; double d = y[1]+vy[1]*t; return sqrt((c-a)*(c-a)+(d-b)*(d-b))-R[0]-R[1];}int main(){ int i,j,k,cas,T,t; scanf("%d",&T); cas=0; while(T--) { scanf("%lf%lf%lf%lf%lf",&x[0],&y[0],&R[0],&vx[0],&vy[0]); scanf("%lf%lf%lf%lf%lf",&x[1],&y[1],&R[1],&vx[1],&vy[1]); double l = 0,r = 1e10; while(r-l > 1e-7) { double ml = l+(r-l)/3; double mr = r-(r-l)/3; if(dis(ml)<=dis(mr))r = mr; else l = ml; } if(dis(l)>=1e-6) printf("%.10lf\n",dis(l)); else { l = 0; while(r-l > 1e-7) { double m = (r+l)/2; if(dis(m)>0)l = m; else r = m; } printf("%.10lf\n",l); } } return 0;}
E.Simple Database
题目:
https://www.bnuoj.com/v3/problem_show.php?pid=51639
题意:
就是给出一个数据库表的创建表、删除表、插入数据,删除数据,修改数据、查询数据的操作。
思路:
大模拟啦,数据结构课都写过广义表好麻烦,想想就好了。
代码:
N/A
F.Training Plan
题目:
https://www.bnuoj.com/v3/problem_show.php?pid=51640
题意:
m天要做n道题,每天的难度为当天做的题的最大难度与最小难度之差的平方,n天的难度之和最小可以是多少。
思路:
考虑到难度是差值的平方,所以难度相近的一起做,所以只要找到已排序的所有题如何分割为n份即可。
显然区间dp,dp[i][j]表示前i天做j题的最小难度,O(n^3)暴力就行了。
代码:
//kopyh#include <bits/stdc++.h>#define INF 0x3f3f3f3f3f3f3f3f#define MOD 1000000007#define N 501using namespace std;int n,m,sum,res,flag;long long a[N],dp[N][N];void init(){ for(int i=1;i<=n;i++)dp[0][i]=INF; dp[0][0] = 0;}int main(){ int i,j,k,cas,T,t,x,y,z; scanf("%d",&T); cas=0; while(T--) { scanf("%d%d",&n,&m); init(); for(i=1;i<=n;i++)scanf("%lld",&a[i]); sort(a+1,a+1+n); for(i=1;i<=m;i++) for(j=1;j<=n;j++) { dp[i][j] = dp[i-1][j]; for(k=1;k<=j;k++) dp[i][j] = min(dp[i][j],dp[i-1][k-1]+abs(a[j]-a[k])*abs(a[j]-a[k])); } printf("%lld\n",dp[m][n]); } return 0;}
G.Certain Maze
题目:
https://www.bnuoj.com/v3/problem_show.php?pid=51641
题意:
给出一个迷宫,每个格子都是一个斜线将各自的4边分成两组,求能否从上面进入下面出去。
思路:
数据只有100*100直接考虑4个方向暴力bfs就行了,开三维数组判断每个格子的每个边是否被便利就行了。
代码:
//kopyh#include <bits/stdc++.h>#define INF 0x3f3f3f3f#define MOD 1000000007#define N 112using namespace std;int n,m,sum,res,flag;struct node{ int x,y,f;};int vis[N][N][4];int dir[4][2]={-1,0,1,0,0,-1,0,1};char s[N][N];bool bfs(){ queue<node>q; memset(vis,0,sizeof(vis)); node a,b; for(int i=1;i<=m;i++) { a.x=1;a.y=i;a.f=0; vis[1][i][0] = 1; q.push(a); } while(!q.empty()) { a=q.front();q.pop(); if(a.x==n&&(a.f==2&&s[a.x][a.y]=='R'||a.f==3&&s[a.x][a.y]=='L')) return true; if(a.f==0) { if(s[a.x][a.y]=='R') { vis[a.x][a.y][3]=1; b.x=a.x;b.y=a.y+1;b.f=2; if(b.x<=n&&b.x>=1&b.y<=m&&b.y>=1&&!vis[b.x][b.y][b.f]) { q.push(b); vis[b.x][b.y][b.f]=1; } } else { vis[a.x][a.y][2]=1; b.x=a.x;b.y=a.y-1;b.f=3; if(b.x<=n&&b.x>=1&b.y<=m&&b.y>=1&&!vis[b.x][b.y][b.f]) { q.push(b); vis[b.x][b.y][b.f]=1; } } } else if(a.f==1) { if(s[a.x][a.y]=='R') { vis[a.x][a.y][2]=1; b.x=a.x;b.y=a.y-1;b.f=3; if(b.x<=n&&b.x>=1&b.y<=m&&b.y>=1&&!vis[b.x][b.y][b.f]) { q.push(b); vis[b.x][b.y][b.f]=1; } } else { vis[a.x][a.y][3]=1; b.x=a.x;b.y=a.y+1;b.f=2; if(b.x<=n&&b.x>=1&b.y<=m&&b.y>=1&&!vis[b.x][b.y][b.f]) { q.push(b); vis[b.x][b.y][b.f]=1; } } } else if(a.f==2) { if(s[a.x][a.y]=='R') { vis[a.x][a.y][1]=1; b.x=a.x+1;b.y=a.y;b.f=0; if(b.x<=n&&b.x>=1&b.y<=m&&b.y>=1&&!vis[b.x][b.y][b.f]) { q.push(b); vis[b.x][b.y][b.f]=1; } } else { vis[a.x][a.y][0]=1; b.x=a.x-1;b.y=a.y;b.f=1; if(b.x<=n&&b.x>=1&b.y<=m&&b.y>=1&&!vis[b.x][b.y][b.f]) { q.push(b); vis[b.x][b.y][b.f]=1; } } } else if(a.f==3) { if(s[a.x][a.y]=='R') { vis[a.x][a.y][0]=1; b.x=a.x-1;b.y=a.y;b.f=1; if(b.x<=n&&b.x>=1&b.y<=m&&b.y>=1&&!vis[b.x][b.y][b.f]) { q.push(b); vis[b.x][b.y][b.f]=1; } } else { vis[a.x][a.y][1]=1; b.x=a.x+1;b.y=a.y;b.f=0; if(b.x<=n&&b.x>=1&b.y<=m&&b.y>=1&&!vis[b.x][b.y][b.f]) { q.push(b); vis[b.x][b.y][b.f]=1; } } } } return false;}int main(){ int i,j,k,cas,T,t,x,y,z; scanf("%d",&T); cas=0; while(T--) { scanf("%d%d",&n,&m); for(i=1;i<=n;i++)scanf("%s",s[i]+1); printf(bfs()?"Yes\n":"No\n"); } return 0;}
I.Cactus Exploration
题目:
https://www.bnuoj.com/v3/problem_show.php?pid=51643
题意:
给出点数和边数,要构造图,使得图联通且没有边同时属于1个以上的环。得分是最大环长度乘以最小环长度,找到最大得分。
思路:
先考虑特殊情况,当m<n-1时显然不联通,当m>2*(n-1)时显然无法满足没有边同时属于1个以上的环,因为最多就是两个点一个环也就是2*(n-1)条边,所以这两种情况都是输出-1。当m==n-1时是一条链输出0,m==n时是一个环输出n*n。
然后考虑一般情况,首先要让所有边都在环上保证总量最大,然后最大值和最小值都尽可能大,所以就是除了最大值之外都是最小值,这样就是要构造一个一个环长度为y其他环为x的图,使得x*y最大。因为y=m-(m-n+1-1)*x,所以答案就是res=(m-(m-n+1-1)*x)*x,一元二次方程组,直接在对称轴附近找整数点求极值就行了。
代码:
//kopyh#include <bits/stdc++.h>#define INF 0x3f3f3f3f#define MOD 1000000007#define N 1123456using namespace std;long long n,m,sum,res,flag,T;int main(){ scanf("%lld",&T); while(T--) { scanf("%lld%lld",&n,&m); if (m < n-1 || m>2*n-2)printf("-1\n"); else if (m == n - 1)printf("0\n"); else if (m == n)printf("%lld\n",n*n); else { res=0; long long p = m/(2*(m-n)); if (p>1 && p<= m/(m-n))res =p*m-(m-n)*p*p; p++; if (p<=m/(m-n))res = max(res,p*m-(m-n)*p*p); printf("%lld\n",res); } } return 0;}
J.Whalyzh's Problem
题目:
https://www.bnuoj.com/v3/problem_show.php?pid=51644
题意:
思路:
将b数组看作完全图的边权于是答案就是在这个图中选一个点集使得这个子图的边权之和/点数最大。
抽象到这一步就和POJ上一道求最大密度子图的题基本等价了,然后跑网络流求之,感谢q神代码。
代码:
#include <bits/stdc++.h>#define INF 1e8#define EPS 1e-8#define N 100using namespace std;struct Edge{ int v; double w; Edge *x;} *e, *lnk[N * N + 9], E[12 * N * N + 9];int TT, S, T, n, m, b[N + 9][N + 9];int g[N * N + 9], h[N * N + 9];int dcmp(double x){ return (x > +EPS) - (x < -EPS);}void add(int u, int v, double w){ e->v = v, e->w = w, e->x = lnk[u], lnk[u] = e++; e->v = u, e->w = 0, e->x = lnk[v], lnk[v] = e++;}double sap(int u, double flw){ if (u == T) return flw; double det, sum = .0; for (Edge *p = lnk[u]; p; p = p->x) if (h[u] == h[p->v] + 1 && dcmp(p->w)) { det = sap(p->v, min(p->w, flw - sum)); p->w -= det; E[(p - E) ^ 1].w += det; if (dcmp((sum += det) - flw) == 0) return sum; } if (h[S] >= m) return sum; if (--g[h[u]] == 0) h[S] = m; ++g[++h[u]]; return sum;}bool check(double x){ m = n + n * (n - 1) / 2; S = ++m, T = ++m; e = E; for (int i = 1; i <= m; ++i) lnk[i] = 0; for (int i = 1; i <= n; ++i) add(i, T, x); int cnt = n; double sum = .0; for (int i = 1; i < n; ++i) for (int j = i + 1; j <= n; ++j) { ++cnt; if (b[i][j]) { sum += b[i][j]; add(S, cnt, b[i][j]); } add(cnt, i, INF); add(cnt, j, INF); } g[0] = m; for (int i = 1; i <= m; ++i) g[i] = h[i] = 0; while (h[S] < m) sum -= sap(S, INF); return sum > EPS;}int main(){ scanf("%d", &TT); while (TT--) { scanf("%d", &n); memset(b, 0, sizeof b); for (int i = 1; i <= n; ++i) for (int j = 1; j <= n; ++j) { int x; scanf("%d", &x); if (i < j) b[i][j] += x; if (i > j) b[j][i] += x; } double l = 0, r = 1000, m; while (fabs(r - l) > EPS) { m = (l + r) / 2; if (check(m)) l = m; else r = m; } printf("%.5f\n", l); } return 0;}
K.ACM Battle
题目:
https://www.bnuoj.com/v3/problem_show.php?pid=51645
题意:
思路:
最小边覆盖是很复杂的,但是这个题要求不能大于10,那就可以暴力了,每次找出第一条边,枚举这条边的头或者是尾然后删掉所有这个节点覆盖的边,继续枚举,最多10层dfs所以就是2^10*m的复杂度。
代码:
<pre name="code" class="cpp">//kopyh#include <bits/stdc++.h>#define INF 0x3f3f3f3f#define MOD 1000000007#define N 1123456using namespace std;int n,m,sum,res,flag;struct edge{ int u,v;}a,b;vector<edge>t,e[10];int dfs(int dep){ if(!t.size())return 0; if(dep==10)return 1; int res=11; int x=t[0].u,y=t[0].v; e[dep] = t; t.clear(); for(int i=0;i<e[dep].size();i++) if(e[dep][i].u!=x && e[dep][i].v!=x) t.push_back(e[dep][i]); res=min(res,dfs(dep+1)); t.clear(); for(int i=0;i<e[dep].size();i++) if(e[dep][i].u!=y && e[dep][i].v!=y) t.push_back(e[dep][i]); res=min(res,dfs(dep+1)); return res+1;}int main(){ int i,j,k,cas,T,x,y,z; scanf("%d",&T); cas=0; while(T--) { scanf("%d%d",&n,&m); t.resize(m); for(i=0;i<m;i++) scanf("%d%d",&t[i].u,&t[i].v); res = dfs(0); if(res>10)printf("GG\n"); else printf("%d\n",res); } return 0;}
- 十四届北师大校赛题解
- 北师大新生赛2014 题解
- 北师大珠海分校2016国庆欢乐赛题解
- 北师大珠海分校2017国庆欢乐赛题解
- 第12届北师大校赛热身赛第二场 B起床的烦恼
- 第12届北师大校赛热身赛第二场 C. 组合数
- 第12届北师大校赛热身赛第二场 A.不和谐的长难句1
- 第二届北师大程序设计竞赛
- 第二届北师大程序设计竞赛
- 第二届北师大程序设计竞赛
- 第二届北师大程序设计竞赛
- 第二届北师大程序设计竞赛
- 第二届北师大程序设计竞赛
- 第二届北师大程序设计竞赛
- 第二届北师大程序设计竞赛
- 第二届北师大程序设计竞赛
- 第十一届北师大程序设计竞赛 by Zoo
- 北师大复试
- git服务器bitnami一键安装
- 大数据基础(四)Ubuntu sbt安装和Spark下的使用
- C#中静态变量的初始化
- 开发2年后我在想什么
- FMDB
- 十四届北师大校赛题解
- 【Android官方文档】翻译Android官方文档-Activities(一)
- 安卓开发学习心得-------WebView的使用
- 给TextView添加点击事件的写法
- 清除windows系统垃圾文件简易脚本(bat)
- 编译与调试--adt
- 跟我学习php字符串常用函数-下篇
- #Spring#spring小程序,简单介绍spring的使用
- 2016湘潭大学“长城信息杯”程序设计邀请赛总结