血崩,做了俩小时只过了一道题,低级错误疯狂的犯。幸好不知道为什么貌似没算分,不然rating要爆炸。
A:呵呵
#include<stdio.h> #include<stdlib.h> int main() { //freopen("input.txt","r",stdin) ; int N; scanf("%d",&N); int x=0,y=0; for (int i=1;i<=N;i++) { int a,b; scanf("%d%d",&a,&b); if (a>b) x++; if (a<b) y++; } if (x>y) printf("Mishka\n"); else if (x<y) printf("Chris\n"); else printf("Friendship is magic!^^\n"); //fclose(stdin); return 0; }
B:先算最外边的环路,然后算capital到非capital,再算capital到capital。注意算后两步的时候要确定两个点是否相邻,如果相邻则不必计算。capital到capital的计算结果要除以2。
#include<stdio.h> #include<stdlib.h> #include<string.h> #include<iostream> using namespace std; int ABS(int x) { if (x>0) return x; else return -1*x; } bool v[150000]; int c[150000],p[150000]; int main() { int N,K; while (cin>>N>>K) { memset(v,false,sizeof(v)); for (int i=1;i<=N;i++) cin>>c[i]; for (int i=1;i<=K;i++) { cin>>p[i]; v[p[i]]=true; } unsigned long long ans=0; for (int i=1;i<N;i++) ans+=c[i]*c[i+1]; if (N!=1) ans+=c[N]*c[1]; long long sum1=0,sum2=0; for (int i=1;i<=N;i++) { if (v[i]) sum1+=c[i]; else sum2+=c[i]; } for (int i=1;i<=K;i++) { int l=p[i]-1,r=p[i]+1; if (l==0) l=N; if (r==N+1) r=1; long long tmp=sum2; if (!v[l]) tmp-=c[l]; if (!v[r]) tmp-=c[r]; ans+=tmp*c[p[i]]; } long long add=0; for (int i=1;i<=K;i++) { int l=p[i]-1,r=p[i]+1; if (l==0) l=N; if (r==N+1) r=1; long long tmp=sum1; tmp-=c[p[i]]; if (v[l]) tmp-=c[l]; if (v[r]) tmp-=c[r]; add+=tmp*c[p[i]]; } ans+=add/2; cout<<ans<<endl; } return 0; }
C:可以想象成车子不动,人具有恒定的水平方向分速度v,竖直方向分速度为0~u。只需使人的位移线与多边形不相交就等价于使车撞不到人。人要避开车子有两种方式,一种是曲线位于多边形上方,这种情况下人可以直接从0时刻开始以最高速度通过。条件是多边形所有顶点与原点的斜率小于u/v。否则,曲线应从多边形下方通过。首先找到到原点斜率最小的一个顶点,如果这个点到原点的斜率大于等于u/v,则人也可以最高速度直接通过。否则人先走到这个点,然后计算逆时针的下一个顶点到这个点的斜率,如果斜率比当前的斜率大,则人可以加速,并以相应的速度移动到与下一个点横坐标相同的位置,直到斜率超过最大斜率或斜率小于0,则剩余路程直接以最大速度通过。
#include<stdio.h> #include<stdlib.h> double ABS(double x) { if (x>0) return x; else return -1*x; } double xl(double x1,double y1,double x2,double y2) { if (ABS(x2-x1)<1e-10) return 1e15; return (y2-y1)/(x2-x1); } double x[12000],y[12000]; int main() { int N; double w,v,u; while (scanf("%d%lf%lf%lf",&N,&w,&v,&u)!=EOF) { bool neg=false; for (int i=1;i<=N;i++) { scanf("%lf%lf",&x[i],&y[i]); if (x[i]<=0) neg=true; } double ans=0; double maxxl=1e-15,minxl=1e15; int maxp,minp; for (int i=1;i<=N;i++) { double tmp=xl(0,0,x[i],y[i]); if (tmp>maxxl) { maxxl=tmp; maxp=i; } if (tmp<minxl && x[i]>0) { minxl=tmp; minp=i; } } double stdxl=u/v; if ((stdxl>=maxxl && neg==false) || minxl>stdxl) { ans=w/u; printf("%.8lf\n",ans); return 0; } int p=minp; double curxl=minxl,cx=x[p],cy=y[p]; ans=x[p]/v; while (curxl<stdxl) { p++; if (p==(N+1)) p=1; double tmpx=xl(cx,cy,x[p],y[p]); if (tmpx<0) { ans+=(w-cy)/u; printf("%.8lf\n",ans); return 0; break; } if (tmpx>stdxl) tmpx=stdxl; curxl=tmpx; ans+=(x[p]-cx)/v; cy+=((x[p]-cx)*curxl); cx=x[p]; } if (cy<w) ans+=(w-cy)/u; printf("%.8lf\n",ans); } return 0; }
D:由于异或自身的结果为0,所以从l到r区间内所有数的异或和等于其中出现奇数次的数的异或和。为了求出出现偶数次数的数的异或和,只需将所有数的异或和再异或上l到r内所有出现过的数的异或和,就可以将本来出现偶数次数的变为奇数次,而奇数次则变为偶数次,得到所求答案。将所有询问按r排序,用数组f[x]保存从1到x所有出现过的数的异或和。当一个数再次出现时,以最新的位置为准,从而使f[r]^f[l-1]的值即为从l到r出现的所有种类数的异或和。
#include <map> #include <set> #include <cmath> #include <queue> #include <bitset> #include <math.h> #include <vector> #include <string> #include <stdio.h> #include <cstring> #include <iostream> #include <algorithm> using namespace std; struct node { int l,r,id; bool operator < (const node a) { return r<a.r; } }q[1010000]; map<int,int> M; int N,a[1010000],f[1010000],pre[1010000],xo[1010000],ans[1010000]; void add(int x,int y) { for (;x<=N;x+=x&-x) f[x]^=y; } int get(int x) { int ret=0; for (;x;x-=x&-x) ret^=f[x]; return ret; } int main() { int i,k,m; scanf("%d",&N); for (i=1;i<=N;i++) { scanf("%d",&a[i]); xo[i]=xo[i-1]^a[i]; } for (i=1;i<=N;i++) { pre[i]=M[a[i]]; M[a[i]]=i; } scanf("%d",&m); for (i=1;i<=m;i++) { scanf("%d%d",&q[i].l,&q[i].r); q[i].id=i; } sort(q+1,q+m+1); for (k=1,i=1;i<=m;i++) { for (;k<=N&&k<=q[i].r;k++) { if (pre[k]) add(pre[k],a[k]); add(k,a[k]); } ans[q[i].id]=xo[q[i].r]^xo[q[i].l-1]^get(q[i].r)^get(q[i].l-1); } for (i=1;i<=m;i++) printf("%d\n",ans[i]); return 0; }
时间: 2024-11-12 17:54:29