题解 P7243 【最大公约数】
首先发现当所有数的
再看到 Subtask 6,发现
for(int i=1;i<=n;++i)for(int j=1;j<=m;++j)if(a[i][j]==1)ans=min(ans,abs(i-X)+abs(j-Y));
发现有解时,变换一遍之后
那么先变换一遍,然后求答案同上
for(re int i=1;i<=n;++i)for(re int j=1;j<=m;++j){ll G1=gcd(a[i-1][j],a[i][j-1]),G2=gcd(a[i+1][j],a[i][j+1]),G3=gcd(G1,G2);b[i][j]=gcd(a[i][j],G3);}
for(re int i=1;i<=n;++i)for(re int j=1;j<=m;++j)if(b[i][j]==1)sum=min(sum,abs(i-X)+abs(j-Y)+(a[i][j]!=1));
但是这样会超时,因为时间复杂度是
再想一下,发现只要求离
容易想到从
最坏的时间复杂度还是 应该能被卡掉?
#include<bits/stdc++.h>
using namespace std;
inline long long gcd(long long a,long long b){long long r;while(b)r=a%b,a=b,b=r;return a;}
const int dx[4]={1,-1,0,0},dy[4]={0,0,-1,1};
long long a[2005][2005],G;
struct Node{int x,y;}t;
bool vis[2005][2005];
queue<Node>q;
int n,m,X,Y;
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;++i)for(int j=1;j<=m;++j)scanf("%lld",&a[i][j]),G=gcd(G,a[i][j]);
if(G!=1){printf("-1");return 0;}
scanf("%d%d",&X,&Y),q.push(Node{X,Y}),vis[X][Y]=true;
while(!q.empty()){
t=q.front(),q.pop(),G=gcd(a[t.x][t.y],gcd(gcd(a[t.x-1][t.y],a[t.x][t.y-1]),gcd(a[t.x+1][t.y],a[t.x][t.y+1])));
if(G==1){printf("%d",abs(t.x-X)+abs(t.y-Y)+(a[t.x][t.y]!=1));return 0;}
for(int i=0;i<4;++i){int nx=t.x+dx[i],ny=t.y+dy[i];if(nx>0&&nx<=n&&ny>0&&ny<=m&&!vis[nx][ny])vis[nx][ny]=true,q.push(Node{nx,ny});}
}
}