P5582 【SWTR-01】Escape

\(b\) 为可用步数序列,长度为 \(m\)

考虑必要性,即每个点都能通过 \(b\) 的线性组合在模 \(n\) 意义下表示出来。

\(b_1x_1+b_2x_2+...+b_mx_m+nx_{m+1}\) 能表示出来 \([0,n)\) 中的每个数,这一部分根据裴蜀定理可得。

这个条件可能是充要的,考虑证明。

定理 31.20:
对于任意正整数 \(a\)\(n\),若 \(d=\gcd(a,n)\),则在 \(Z_n\) 中,\(<a>=<d>\)

引理
环大小为 \(n\),若初始在位置 \(p\),每次跳 \(k\) 步,\(k|n\),则到达的位置一定是 \(x\equiv p \pmod{k}\)
证明:考虑原先到达的位置 \(x\equiv 0 \pmod{k}\),初始位置在 \(p\) 可看做初始位置在 \(0\),跳完后再向右跳一次 \(p\) 步,因为跳 \(k\) 步能取遍且互不相同的位置 \(x\in[0,n),k|x\),所以你再向右跳显然也能取遍,且互不相同。

考虑先跳 \(b_1\),即记 \(d=\gcd(b_1,n)\),跳完了,\(d,2d \ ... \ (n/d-1)d,0\),那么考虑只要每次跳完这样的一个循环,能够位移到组内另一个地方即可。这样每一次跳到的都是不一样的。

即问题变成了 \(b_2,b_3 \ ... \ b_m\) 跳完 \([0,d)\),考虑结构一样,如此操作下去,最终变成 \(b_m\) 跳完 \([0,\gcd(n,b_1,b_2\ ... \ b_{m-1}))\),显然在 \(Z_{\gcd(n,b_1,b_2\ ... \ b_{m-1})}\) 中,\(|<b_m>|=\gcd(n,b_1,b_2\ ... \ b_{m-1})\),因此可以跳完。然后子问题可以完成,则上级问题推回去也可以完成。

#include <bits/stdc++.h>
#define ll long long
#define pb push_back
using namespace std;
const int N=(int)(1e6+5);
bool vis[N];
int n,m;

int gcd(int x,int y) {
	return !y?x:gcd(y,x%y);
}

void sol() {
	cin>>n>>m;
	for(int i=1;i<=n;i++) vis[i]=0;
	for(int i=1;i<=m;i++) {
		int x; cin>>x; vis[x]=1; 
	}
	int qwq=0;
	for(int i=1;i<=n;i++) {
		if(vis[i]) continue ;
		if(!qwq) qwq=gcd(i,n);
		else qwq=gcd(qwq,gcd(i,n));
	}
	if(!qwq) {
		cout<<"-1\n"; return ;
	}
	for(int i=1;i<=n;i++) {
		if(i%qwq!=0) {
			cout<<"-1\n";
			return ;
		}
	}
	cout<<n<<'\n';
}

signed main() {
	cin.tie(0); ios::sync_with_stdio(false);
	int T; cin>>T; while(T--) sol();
	return 0; 
}
posted @ 2023-01-10 16:16  FxorG  阅读(27)  评论(0编辑  收藏  举报