题意
给出一个点 ((x,y)) ,满足 (gcd(x,y)>1)。每次可以从当前的点到达其周围 (8) 个点中满足坐标 (gcd(x',y')>1) 的点中的一个,定义 (P_t) 为返回出发点的概率,求 (lim limits_{t ightarrowinfty}P_t)。
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6853
分析
当起点和对角线联通,概率为 (0)。可以走的联通块的大小并不会很大,可以直接 (bfs) 搜索,判断是否联通。否则答案为 "起点度数+1" 除以 "总度数+n"。
关于这两个结论,自己并不会证明,希望大佬指点。
代码
#include <bits/stdc++.h>
#define pb push_back
using namespace std;
typedef long long ll;
typedef pair<ll,ll>pll;
int dx[8]={-1,-1,-1,0,1,1,1,0};
int dy[8]={-1,0,1,1,1,0,-1,-1};
queue<pll>que;
map<int,map<ll,ll> >mp;
vector<pll>point;
ll gcd(ll a,ll b)
{
return b?gcd(b,a%b):a;
}
bool check(ll x,ll y)
{
if(gcd(x,y)>1&&mp[x][y]==0) return 1;
return 0;
}
bool bfs(ll sx,ll sy)//联通块不大
{
mp.clear();
point.clear();
while(!que.empty())
que.pop();
mp[sx][sy]=1;
que.push(make_pair(sx,sy));
while(!que.empty())
{
pll now=que.front();
que.pop();
if(now.first==now.second) return 1;
point.pb(now);
for(int i=0;i<8;i++)
{
ll tx=now.first+dx[i];
ll ty=now.second+dy[i];
if(check(tx,ty))
{
if(tx==ty) return 1;
que.push(make_pair(tx,ty));
mp[tx][ty]=1;
}
}
}
return 0;
}
int cont(ll x,ll y)
{
int cot=0;
for(int i=-1;i<=1;i++)
{
for(int j=-1;j<=1;j++)
{
if(gcd(x+i,y+j)>1)
cot++;
}
}
return cot;
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
ll x,y;
int tol=0,cnt=0;
scanf("%lld%lld",&x,&y);
if(bfs(x,y))
{
printf("0/1
");
continue;
}
for(int i=0;i<point.size();i++)
tol+=cont(point[i].first,point[i].second);//总度数+n
cnt=cont(x,y);//起点度数+1
ll g=gcd(tol,cnt);
printf("%lld/%lld
",cnt/g,tol/g);
}
return 0;
}