北京师范大学第十二届程序设计竞赛
Posted jzdwajue
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了北京师范大学第十二届程序设计竞赛相关的知识,希望对你有一定的参考价值。
感觉像是个人赛。只是要是个人赛的话他们真的是太牛了。。。
全然被虐爆了有没有啊。
整体来说题目不是非常难,以下就粘一下代码吧。
队友看的A,看完就发现了水题本质。可是敲的不是非常顺利。
。。是由于太久没做比赛么。。
#include<algorithm> #include<iostream> #include<cstring> #include<vector> #include<cstdio> #include<cmath> #include<queue> #include<stack> #include<map> #include<set> #define LL long long #define inf 0x3f3f3f3f #define CLR(a, b) memset(a, b, sizeof(a)) using namespace std; const int maxn = 100086; const int INF = 0x3f3f3f3f; int str[maxn]; int main() { int n,i,j; int m,k; str[1]=0; for(i=2; i<100; i++) { str[i]=str[i-1]+i*i; } str[100]=inf; while(scanf("%d", &n) != EOF) { int tmp = 0; for(i=0; i<n; i++) { scanf("%d%d",&m,&k); tmp+=m*k; } int pos =0; for(i=1; i<=100; i++) { if(tmp>=str[i])pos = i; } printf("Team Liserious‘ rank is %d\n",pos); } return 0; }
B题看完就发现了,公式题一个,,,可是。读错题了。
。。经队友矫正,又读错了。。。=.=!!(什么情况,要gg了,过了非常久最终懂了题目让干什么,推了下公式就A了,题目给的是当前天和过后一天细菌的情况,然后问n天后的情况。
#include<algorithm> #include<iostream> #include<cstring> #include<vector> #include<cstdio> #include<cmath> #include<queue> #include<stack> #include<map> #include<set> #define LL long long #define CLR(a, b) memset(a, b, sizeof(a)) using namespace std; int main() { LL b, a; int T;LL n; scanf("%d", &T); while(T --) { cin >> a >> b >> n; LL x, y; y = (b - a) / 2; x = a - y; n ++; double ans; if((n-1)/2 > (n-2)/2) y *= 3; ans = log10(x+y+0.0) + log10(3+0.0)*((n - 2) / 2); printf("%.7f\n", ans); } }D题好像就是求一下向量夹角即可了。。
#include<stdio.h> #include<string.h> #include<math.h> #include<algorithm> using namespace std; const double pi=3.14159265358; const double eps=1e-8; int dblcmp(double x) { if(x<-eps) return -1; if(x>eps) return 1; return 0; } struct point { double x,y,k; point(double a=0,double b=0,double c=0) { x=a,y=b,k=c; } point operator-(const point &a) { return point(x-a.x,y-a.y,k); } void input() { scanf("%lf%lf%lf",&x,&y,&k); } bool friend operator<(const point &a,const point &b) { return a.k<b.k; } } p[1010],st,en,s1,s2; double dot(point a, point b) { return a.x * b.x + a.y * b.y; } double cross(point a, point b) { return a.x * b.y - a.y * b.x; } double angle(point a, point b) { double res = acos(dot(a, b)/((sqrt(a.x * a.x + a.y * a.y)*sqrt(b.x * b.x + b.y * b.y)))); if (dblcmp(cross(a, b)- 0) < 0) return 2 * pi - res; return res; } int main() { int t,n; scanf("%d",&t); while(t--) { scanf("%d",&n); for(int i=0; i<n; i++) p[i].input(); sort(p,p+n); scanf("%lf%lf%lf%lf",&st.x,&st.y,&en.x,&en.y); s1=p[0]-p[1]; s2=st-en; double ans=angle(s1,s2)/pi*180.00; if(ans>180.00) ans=360.00-ans; printf("%.3f\n",ans); } }H居然11分钟就有人A掉了,太厉害了。。
。
推了下,既然是汉诺塔,就肯定是有递推关系了。
t[a+1] = 1/3*t[a]+2/3*(t[a] + 1 + f[a]);f[a]表示a个盘子的正常汉诺塔问题,即本来是在一个位置A,转移到C的步数。
#include<algorithm> #include<iostream> #include<cstring> #include<vector> #include<cstdio> #include<cmath> #include<queue> #include<stack> #include<map> #include<set> #define LL long long #define MP make_pair #define CLR(a, b) memset(a, b, sizeof(a)) using namespace std; const int maxn = 55; const LL INF = 1ll << 60; int main() { int T, n; scanf("%d", &T); while(T --) { scanf("%d", &n); double ans = 2.0/3.0; for(int i = 2; i <= n; i ++) { ans = 1.0/3.0*ans + 2.0/3.0*(ans + (1ll << (i - 1))); } printf("%.2f\n", ans); } }
C题每次都询问右上角,显然询问值大于当前值的话,就能够删掉最右边一列,假设小于当前值的话就删掉最上边一行。就这样。。。输出非常特别啊
#include<algorithm> #include<iostream> #include<cstring> #include<vector> #include<cstdio> #include<cmath> #include<queue> #include<stack> #include<map> #include<set> #define LL long long #define MP make_pair #define CLR(a, b) memset(a, b, sizeof(a)) using namespace std; const int maxn = 100100; const int INF = 0x3f3f3f3f; int main() { int T, n, m, k; scanf("%d", &T); while(T --) { scanf("%d%d%d", &n, &m, &k); bool flag = false; int r = 1, c = m; while(r <= n && c >= 1) { printf("%d %d\n", r, c);fflush(stdout); int tmp; scanf("%d", &tmp); if(tmp == k) { flag = true; break; } if(tmp < k) r ++; else c --; } if(flag) puts("YES"),fflush(stdout); else puts("NO"),fflush(stdout); } }
J题正常搞肯定超时。这样的题。不是式子满足交换结合律之类,就是乘法特别,队友推出时满足这样 (AB)((AT).+1(BT).+1) = (A*((AT).+1))(B*((BT).+1)),这样就妥妥的能AC了。
#include<algorithm> #include<iostream> #include<cstring> #include<vector> #include<cstdio> #include<cmath> #include<queue> #include<stack> #include<map> #include<set> #define LL long long #define MP make_pair #define CLR(a, b) memset(a, b, sizeof(a)) using namespace std; const int maxn = 55; LL ans[3000][3000]; struct Mr { LL m[maxn][maxn]; int r, c; void pt() { for(int i = 0; i < r; i ++) for(int j = 0; j < c; j ++) printf("%lld%c", m[i][j], j == c - 1?F题dp一枚。每次枚举出每组的情况。然后结合前面能组成的情况,dp就能够了。‘\n‘ : ‘ ‘); } }; Mr Tadd1(Mr a) { Mr ret; ret.r = a.c; ret.c = a.r; for(int i = 0; i < a.r; i ++) for(int j = 0; j < a.c; j ++) { ret.m[j][i] = a.m[i][j] + 1; } return ret; } Mr Mul(Mr a, Mr b) { Mr ret; ret.r = a.r; ret.c = b.c; for(int i = 0; i < a.r; i ++) { for(int j = 0; j < b.c; j ++) { ret.m[i][j] = 0; for(int k = 0; k < a.c; k ++) { ret.m[i][j] += a.m[i][k] * b.m[k][j]; } } } return ret; } void OR(Mr a, Mr b) { for(int i = 0; i < a.r; i ++) { for(int j = 0; j < a.c; j ++) { for(int k = 0; k < b.r; k ++) { for(int s = 0; s < b.c; s ++) { ans[i*b.r+k][j*b.c+s] = a.m[i][j] * b.m[k][s]; } } } } } Mr a, at, b, bt; int main() { int T, n, m, p, q; scanf("%d", &T); while(T --) { scanf("%d%d%d%d", &n, &m, &p, &q); a.r = n, a.c = m; b.r = p, b.c = q; for(int i = 0; i < n; i ++) { for(int j = 0; j < m; j ++) scanf("%lld", &a.m[i][j]); } for(int i = 0; i < p; i ++) { for(int j = 0; j < q; j ++) scanf("%lld", &b.m[i][j]); } at = Tadd1(a); bt = Tadd1(b); OR(Mul(a, at), Mul(b, bt)); for(int i = 0; i < n*p; i ++) { for(int j = 0; j < n*p; j ++) { printf("%lld%c", ans[i][j], j == n*p - 1 ?
‘\n‘ : ‘ ‘); } } return 0; }
dp[i]表示sum个位置哪个位置被占用了。时间复杂度不明。
。
。
#include<algorithm> #include<iostream> #include<cstring> #include<vector> #include<cstdio> #include<cmath> #include<queue> #include<stack> #include<map> #include<set> #define LL long long #define MP make_pair #define CLR(a, b) memset(a, b, sizeof(a)) using namespace std; const int maxn = 25; LL dp[(1<<20)+100]; vector<int> a[maxn], now, nxt; int sum, n, b[7]; void dfs(int idx) { if(idx >= n) return; int sz = a[idx].size(), ca = 0; for(int j = 0; j < sz; j ++) b[j] = j, ca += a[idx][j]; b[sz] = 0; nxt.clear(); for(int i = 0; i < sum; i ++) { do { int fu = 0, ta = i; if(i + ca - a[idx][b[0]] >= sum) continue; for(int j = 0; j < sz; j ++) { fu |= (1 << (ta)); ta += a[idx][b[j + 1]]; } for(int j = 0; j < now.size(); j ++) if(!(fu&now[j])) { if(!dp[fu|now[j]]) nxt.push_back(fu|now[j]); dp[fu|now[j]] += dp[now[j]]; } } while(next_permutation(b, b + sz)); } now.clear(); for(int i = 0; i < nxt.size(); i ++) now.push_back(nxt[i]); dfs(idx + 1); } int main() { while(scanf("%d", &n) != EOF) { sum = 0; for(int i = 0; i < n; i ++) { int m, tmp;a[i].clear(); scanf("%d", &m); sum += m; while(m --) { scanf("%d", &tmp); a[i].push_back(tmp); } } now.clear(); CLR(dp, 0); now.push_back(0); dp[0] = 1; dfs(0); printf("%lld\n", dp[(1<<sum)-1]); } }
G题有类似的题目,错到最后。发现模板有问题。。。汗。赛后两分钟换了个模板就A了。。。闹哪样啊这是。
(代码风格能够看出。。
。显然不是我做的,全然不知道怎么做啊=,=!!)
#include<stdio.h> #include<math.h> #include<string.h> #include<stdlib.h> double Dis(double x1, double y1, double x2, double y2) { double dx=x1-x2; double dy=y1-y2; return sqrt(dx*dx+dy*dy); } void Get_KL(double L, double x, double y, int &k, int &l, double &cd) { k=floor((2.0*x)/(3.0*L)); l=floor((2.0*y)/(sqrt(3.0)*L)); double d1, d2, x1, y1, x2, y2; if ((k+l)&1) { x1=k*L*1.5; y1=(l+1.0)*L*sqrt(3.0)*0.5; x2=(k+1.0)*L*1.5; y2=l*L*sqrt(3.0)*0.5; d1=Dis(x1,y1, x,y); d2=Dis(x2,y2, x,y); if (d1>d2) { k++; cd=d2; } else { l++; cd=d1; } } else { x1=k*L*1.5; y1=l*L*sqrt(3.0)*0.5; x2=(k+1.0)*L*1.5; y2=(l+1.0)*L*sqrt(3.0)*0.5; d1=Dis(x1,y1, x,y); d2=Dis(x2,y2, x,y); if (d1>d2) { k++,l++; cd=d2; } else cd=d1; } } int My_Abs(int x) { if (x<0) return -x; return x; } int main (void) { double L, x1, y1, x2, y2, cd1, cd2; int k1, l1, k2, l2, ans; int t; scanf("%d",&t); while (t--) { scanf("%lf %lf %lf %lf %lf",&L,&y1,&x1,&y2,&x2); y1=-y1,y2=-y2; Get_KL(L, x1, y1, k1, l1, cd1); Get_KL(L, x2, y2, k2, l2, cd2); if (k1==k2&&l1==l2) printf("%d\n",0); else { ans=0; if (My_Abs(k1-k2) > My_Abs(l1-l2)) ans=My_Abs(k1-k2); else ans=My_Abs(k1-k2)+(My_Abs(l1-l2)-My_Abs(k1-k2))/2; printf("%d\n", ans); } } return 0; }
以上是关于北京师范大学第十二届程序设计竞赛的主要内容,如果未能解决你的问题,请参考以下文章
湖南省第十二届大学生计算机程序设计竞赛 G Parenthesis
“山大地纬杯”第十二届山东省ICPC大学生程序设计竞赛 AHK
湖南省第十二届大学生计算机程序设计竞赛---Parenthesis(线段树求区间最值)