G. Singhal and Multiplication(数论)
题目链接:https://codeforces.com/gym/102767/problem/G
题目大意:给定一段序列
{
a
1
,
a
2
,
⋯
,
a
n
}
\{a_1,a_2,\cdots,a_n\}
{a1,a2,⋯,an},要你寻找一段连续子序列
{
a
i
,
⋯
,
a
j
}
(
1
≤
i
≤
j
≤
n
)
\{a_i,\cdots ,a_j\}(1 \le i \le j \le n)
{ai,⋯,aj}(1≤i≤j≤n),使得
∏
k
=
i
j
a
k
≡
1
m
o
d
n
\prod \limits_{k=i}^{j}a_k \equiv 1 \space mod \space n
k=i∏jak≡1 mod n。如果存在这样的子序列,输出
m
i
n
(
j
−
i
+
1
)
min(j-i+1)
min(j−i+1),即这样的子序列的最小长度,反之不存在的话就输出
0
0
0。
题解:考虑逆元的定义,对于任意一个满足gcd(m,n)
≠
\neq
= 1的整数m,则m在模n意义下不存在逆元。假设连续子序列
{
a
1
,
⋯
,
a
r
,
⋯
,
a
i
,
⋯
,
a
j
}
\{a_1,\cdots ,a_r,\cdots ,a_i,\cdots ,a_j \}
{a1,⋯,ar,⋯,ai,⋯,aj},则有
∏
k
=
r
j
a
k
≡
∏
t
=
r
i
−
1
a
t
m
o
d
n
\prod \limits_{k=r}^{j}a_k \equiv \prod \limits_{t=r}^{i-1}a_t\space mod \space n
k=r∏jak≡t=r∏i−1at mod n,其中gcd(
a
r
−
1
a_{r-1}
ar−1,n)
≠
1
⇒
∏
k
=
1
r
−
1
a
k
≡
0
m
o
d
n
\neq 1 \Rightarrow \prod \limits_{k=1}^{r-1}a_k \equiv 0 \space mod \space n
=1⇒k=1∏r−1ak≡0 mod n 且
∏
k
=
i
j
a
k
≡
1
m
o
d
n
\prod \limits_{k=i}^{j}a_k \equiv 1 \space mod \space n
k=i∏jak≡1 mod n。易知,我们不需要考虑位置r之前的子序列的影响,因为子序列是连续的,如果子序列拓展到位置r之前的元素,会令子序列一定会包含元素
a
r
−
1
a_{r-1}
ar−1,使得子序列的模n意义下的连乘结果不可能为1。记zpos为当前序列元素之前的最后一个满足gcd(
a
z
p
o
s
a_{zpos}
azpos,n)
≠
\neq
= 1的序列元素下标位置;记prepro为序列的前缀积,同时如果发现当前处理的位置i的前缀积为0时(即
∏
k
=
z
p
o
s
+
1
i
a
k
≡
0
m
o
d
n
\prod \limits_{k=zpos+1}^i a_k \equiv 0 \space mod \space n
k=zpos+1∏iak≡0 mod n),令prepro[i]只等于
a
i
a_{i}
ai,这样处理的话我们便能保证prepro中的元素一直不会为0(除非
a
i
≡
0
m
o
d
n
a_i\equiv 0 \space mod \space n
ai≡0 mod n);记pro记录前缀积结果的出现位置,这样我们便能确定是否有同样的前缀积结果出现,还能得到这组子序列的长度,同样的,如果发现当前处理的位置i的前缀积为0时,把pro进行清空操作,因为
a
i
a_i
ai之前的序列元素会影响后续子序列连乘的结果,使得连乘结果永远不能为1。
下面便是根据上面解题思路得出的AC代码(记得开long long,否则会被卡WA)。
#include<bits/stdc++.h>
#define int long long
using namespace std;
struct fastio{fastio(){ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);}}fio;
signed main(){
int t,n,m;
cin>>t;
while(t--){
cin>>n;
vector<int> prepro(n+1,0);
map<int,int> pro;
int res=0x3f3f3f3f,zpos=0;
for(int i=1;i<=n;++i){
cin>>m;
m%=n;
if(m==1) res=1;
if(__gcd(m,n)!=1){
prepro[i]=0;
zpos=i;
pro.clear();
continue;
}
if(!prepro[i-1]) prepro[i]=m;
else prepro[i]=(prepro[i-1]*m)%n;
if(prepro[i]==1) res=min(res,i-zpos);
if(pro.count(prepro[i])) res=min(res,i-pro[prepro[i]]);
if(prepro[i]) pro[prepro[i]]=i;
}
cout<<(res==0x3f3f3f3f?0:res)<<endl;
}
}