ARC118D Hamiltonian Cycle

有个质数(P),然后有个图,点编号为(1dots P-1)。给出数字(a,b)

对于(iin [1,P-1]),连双向边((i,aimod P),(i,bimod P))

构造一条哈密顿回路。

(Ple 10^5)


(n)(a)在模意义下的阶,记(H={a^i|iin[0,n)})。记最小的满足(b^min H)(m)(m)

首先有解的必要条件是任意数都能表示成(a^ib^j)。可以证明,如果有这样的表示方法,那一定存在(iin[0,n),jin[0,m))的表示,且唯一。

存在性显然。唯一性:如果存在(a^{i_1}b^{j_1}=a^{i_2}b^{j_2}),那么有(a^{i_1-i_2}=b^{j_1-j_2}),可得(b^{j_1-j_2}in H),根据(m)的定义可得(j_1-j_2equiv 0pmod m)

这也说明了能被表示的数的个数是(nm)。因此(P-1=nm)是有解的必要条件。然后构造使得它为充分条件:

可以看做一个二维的网格((n)(m)列),其中最下面一行往下走可以到最上面一行同一列,最右边一列往右走可以到左边某一列但不一定同行(因为这样比较阴间所以尝试不走这样的边将其构造得出)。

官方题解中的Method3(可以处理(n,m>1)时的所有情况):

如果(n)为偶数,可以直接蛇形构造,最后在点((n-1,0))跳到((0,0))

如果(n)为奇数,把(a,b)交换,可以证明交换后得到(n')一定会是偶数。

证明即证(a,b)的阶至少有一个为偶数。

设原根为(g),则(a,b)可以分别表示为(g^A,g^B),阶分别为(frac{P-1}{A},frac{P-1}{B})。如果阶都是奇数,那么(A,B)都是偶数,当(P)为奇素数时,能表示的值(g^x)一定满足(x)是偶数,于是(x)为奇数的就表示不出来,与(a^ib^j)可以表示所有数矛盾。


using namespace std;
#include <bits/stdc++.h>
#define N 100005
#define ll long long
int P,a,b,invb;
ll qpow(ll x,ll y=P-2){
	ll r=1;
	for (;y;y>>=1,x=x*x%P)
		if (y&1)
			r=r*x%P;
	return r;
}
bool vis[N];
int n,m;
void getnm(int a,int b){
	memset(vis,0,sizeof(bool)*P);
	n=0;
	for (int x=1;!vis[x];x=(ll)x*a%P)
		vis[x]=1,++n;
	m=1;
	for (int x=b;!vis[x];x=(ll)x*b%P)
		++m;
}
int main(){
//	freopen("in.txt","r",stdin);
	scanf("%d%d%d",&P,&a,&b);
	getnm(a,b);
	if (n*m<P-1){
		printf("No
");
		return 0;
	}
	if (n==1 && m==1){
		printf("Yes
1 1
");
		return 0;	
	}
	if (n&1)
		swap(a,b),getnm(a,b);
	invb=qpow(b);
	printf("Yes
");
	int x=1;
	for (int i=0;i<n;i+=2){
		printf("%d ",x);
		for (int j=1;j<m;++j){
			x=(ll)x*b%P;
			printf("%d ",x);
		}
		x=(ll)x*a%P;
		printf("%d ",x);
		for (int j=m-2;j>=0;--j){
			x=(ll)x*invb%P;
			printf("%d ",x);
		}
		x=(ll)x*a%P;
	}
	printf("1
");
	return 0;
}
原文地址:https://www.cnblogs.com/jz-597/p/14757469.html