AC:09,10
很容易想到,如果先手到达最长点对之一,则必败。(后手可以走最长点对的另一点,使得先手无处可走)
对于一个游戏,把他转化为无向图。
先找出当前图中最长的边d。
然后把边长为d的所有边连接的点都删去(这些点称为必败点,到达即必败),然后这些点设为一层(称为必败层,即先手到这一层必败)
然后得到新的无向图。重复上述操作。
直到图只剩一个点,或者为空,最后的一个点设为一层。
显然这是一个分层图,只能由底层走向高层,且先跨层的人必败。
而且每层的距离都相同,说明每层最多只能移动一次。
即:若一个点x在某一层,他可以选在在这一层一定,则下一步的人必须跨层。
由此得到必胜策略:
对于点x,若其所在层点数不为1,则必胜,否则必败(必须跨层)
#include
using namespace std;
typedef long long ll;
typedef long double ld;
#define ls (o<<1)
#define rs (o<<1|1)
#define pb push_back
const double PI= acos(-1.0);
const int N = 2000+7;
/*
int head[M],cnt=1;
void init(){cnt=1,memset(head,0,sizeof(head));}
struct EDGE{int to,nxt,w;}ee[M*2];
void add(int x,int y,int w){ee[++cnt].nxt=head[x],ee[cnt].w=w,ee[cnt].to=y,head[x]=cnt;}
*/
struct node{
ll x,y;
}p[N];
struct EDGE{
int u,v;ll dis;
// bool operator < (const EDGE &r)const{
// return dis>T;
while(T--)
{
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%lld%lld",&p[i].x,&p[i].y),vs[i]=0;
int sz=0;
for(int i=1;i<=n;i++)
for(int j=1;j=1;i--)
{
int u=e[i].u,v=e[i].v;
if(vs[u]||vs[v])continue;
int j=i;
vectorvv;
while(j&&e[j].dis==e[i].dis)
{
if(vs[e[j].u]||vs[e[j].v])
{
j--;
continue;
}
vv.pb(j);
j--;
}
for(auto x:vv)
vs[e[x].u]=vs[e[x].v]=1;
i=j+1;
}
if(vs[1])puts("YES");
else puts("NO");
}
return 0;
}
思维水题
显然若走到(i,i)则会无限游荡。则回到起点的概率为0.
若无法走,则必定留在原地。
现在问题是多个格子求留在起点的概率。
考虑上图,起点s,只在三个格子里游荡。若走无限步,则起点对结果不影响。
只考虑每个点由会由哪些情况到达即可:
对于点s:s停留会到达s,点1会到达s,共2种
对于点1:1停留在1,点2,s会到达1,共3种
对于点2:2停留在2,点1会到达2,共2种
则停留在点x的概率是总情况除到达点x的情况即可。
证明我也不会,但感性很容理解
而且题目给了样例,很容易猜出来
#include
using namespace std;
typedef long long ll;
#define ls (o<<1)
#define rs (o<<1|1)
#define pb push_back
const double PI= acos(-1.0);
const int M = 1e5+7;
/*
int head[M],cnt=1;
void init(){cnt=1,memset(head,0,sizeof(head));}
struct EDGE{int to,nxt,w;}ee[M*2];
void add(int x,int y,int w){ee[++cnt].nxt=head[x],ee[cnt].w=w,ee[cnt].to=y,head[x]=cnt;}
*/
ll gcd(ll a,ll b)
{
if(b==0)return a;
return gcd(b,a%b);
}
bool flag=false;
int sm=0;
map,int>mp;
void dfs(ll x,ll y)
{
//cout<<"-- "<1)
{
// cout<<"=-=-==- "<>T;
while(T--)
{
ll x,y;
scanf("%lld%lld",&x,&y);
int fz=0;
sm=0;flag=false;mp.clear();
for(int i=-1;i<=1;i++)
for(int j=-1;j<=1;j++)
if(gcd(x+i,y+j)>1)fz++;
dfs(x,y);
if(flag)
{
puts("0/1");
continue;
}
int c=gcd(fz,sm);
printf("%d/%d\n",fz/c,sm/c);
}
return 0;
}
/*
3
18 16
18 6
18 8
*/