zoukankan      html  css  js  c++  java
  • 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;
    }
    
  • 相关阅读:
    12.12 怀北滑雪场滑雪记
    datetime类型offset-aware与offset-navie
    Django-models中的choise
    什么是__name__()
    单机Ubuntu安装第二个Mysql服务
    Ubuntu下的Python安装
    设置mysql允许外网访问
    Ubuntu初次设置root密码
    使用VMware+Ubuntu,无法切换大小写的异常处理
    XShell/Xftp 无法连接 Ubuntu20
  • 原文地址:https://www.cnblogs.com/jz-597/p/14757469.html
Copyright © 2011-2022 走看看