2020杭电多校第七场
T1007 Game
如果先手初始点在距离最远的点对上,那么先手必胜,据此,可以推广到距离次远的点对,距离第三远的点对,先手都是必胜的。所以点数是偶数时先手必胜,点数是奇数时先手如果在:除距离最长、距离次长、距离第三长...剩下的最后一个点上,那么先手必败,否则先手必胜。
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int N=2010; 5 struct node{ 6 int u,v; 7 double d; 8 }a[N*N]; 9 struct Point{ 10 double x,y; 11 }; 12 Point p[N]; 13 bool vis[N]; 14 bool cmp(const node &a,const node &b){ 15 return a.d>b.d; 16 } 17 double dis(Point A,Point B){//两点间的距离 18 return sqrt((A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y)); 19 } 20 int main() 21 { 22 int T; 23 scanf("%d",&T); 24 while(T--){ 25 memset(vis,0,sizeof(vis)); 26 int n; 27 scanf("%d",&n); 28 for(int i=1;i<=n;i++){ 29 scanf("%lf%lf",&p[i].x,&p[i].y); 30 } 31 if(n%2==0){ 32 printf("YES\n"); 33 continue; 34 } 35 int cnt=0; 36 for(int i=1;i<=n;i++){ 37 for(int j=i+1;j<=n;j++){ 38 a[++cnt].u=i; 39 a[cnt].v=j; 40 a[cnt].d=dis(p[i],p[j]); 41 } 42 } 43 sort(a+1,a+cnt+1,cmp); 44 int num=0; 45 for(int i=1;i<=cnt;i++){ 46 int u=a[i].u,v=a[i].v; 47 if(!vis[u]&&!vis[v]){ 48 vis[u]=vis[v]=1; 49 ++num; 50 if(num==n/2) break; 51 } 52 } 53 if(vis[1]) printf("YES\n"); 54 else printf("NO\n"); 55 } 56 return 0; 57 }
T1009 Increasing and Decreasing
队友过的,代码先贴上。
1 #include<bits/stdc++.h> 2 #define ll long long 3 using namespace std; 4 5 int n,x,y; 6 int a[100009]; 7 8 int main(){ 9 int t; 10 cin>>t; 11 while(t--){ 12 scanf("%d%d%d",&n,&x,&y); 13 int pos=n; 14 if((x==1&&y!=n)||(y==1&&x!=n)||(x+y>n+1)){ 15 cout<<"NO"<<endl; 16 continue; 17 } 18 while(pos>y){ 19 int po=pos; 20 for(int i=y-1;i>=0;i--){ 21 a[pos]=po-i; 22 pos--; 23 } 24 }//printf("%d",a[1]); 25 //for(int i=2;i<=n;i++)printf(" %d",a[i]);cout<<endl; 26 int u=n/y; 27 if(u*y==n)u--; 28 int l=n-y*u; 29 while(l+u<x)l+=y,u--; 30 int r=x-u; 31 //cout<<l<<endl; 32 for(int i=1;i<r;i++){ 33 a[i]=i; 34 } 35 a[r]=l; 36 for(int i=r+1;i<=a[r];i++){ 37 a[i]=--l; 38 } 39 printf("YES\n");printf("%d",a[1]); 40 for(int i=2;i<=n;i++)printf(" %d",a[i]);cout<<endl; 41 42 } 43 return 0; 44 }
T1010 Jogging
队友想出来的,本质上就是:分母是:符合条件的点形成的一个连通块,连通块中所有的点周围可以到达的点(包括自己)的个数之和,分子就是起始点周围可以到达的点(包括自己)的个数之和。
如果连通块包含了对角线上的点(即x=y的点),说明可以到达无穷远,从而回到初始点的概率可以视为0。
从起始点bfs统计即可。
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int d[8][2]={1,0,0,1,-1,0,0,-1,1,1,1,-1,-1,1,-1,-1}; 5 map<pair<ll,ll>,int>mp; 6 ll num; //分母 7 struct node{ 8 ll x,y; 9 node(ll a,ll b){ 10 x=a,y=b; 11 } 12 }; 13 bool bfs(ll dx,ll dy){ 14 num=0; 15 mp.clear(); 16 queue<node>q; 17 q.push(node(dx,dy)); 18 mp[make_pair(dx,dy)]=1; 19 while(!q.empty()){ 20 node u=q.front(); 21 q.pop(); 22 if(u.x==u.y){ 23 return 0; 24 } 25 ll tmp=0; 26 for(int i=0;i<8;i++){ 27 ll nx=u.x+d[i][0]; 28 ll ny=u.y+d[i][1]; 29 if(__gcd(nx,ny)==1){ 30 continue; 31 } 32 tmp++; 33 if(!mp[make_pair(nx,ny)]){ 34 mp[make_pair(nx,ny)]=1; 35 q.push(node(nx,ny)); 36 } 37 } 38 num+=tmp+1; 39 } 40 return 1; 41 } 42 int main() 43 { 44 int T; 45 scanf("%d",&T); 46 while(T--){ 47 ll sx,sy; 48 scanf("%lld%lld",&sx,&sy); 49 if(bfs(sx,sy)){ 50 ll tmp=0; //分子 51 for(int i=0;i<8;i++){ 52 ll nx=sx+d[i][0]; 53 ll ny=sy+d[i][1]; 54 if(__gcd(nx,ny)>1){ 55 tmp++; 56 } 57 } 58 tmp++; 59 ll c=__gcd(tmp,num); //化成最简形式 60 ll u=tmp/c,v=num/c; 61 printf("%lld/%lld\n",u,v); 62 } 63 else printf("0/1\n"); 64 } 65 return 0; 66 }