题意
这个题目的意思就是什么呢?
给你一个数
n
n
n,现在让你找到
1
1
1~
n
−
1
n-1
n−1的最长子序列(非
l
i
s
lis
lis),子序列全部元素相乘
m
o
d
n
mod n
modn等于
1
1
1,请你先输出长度,然后从小到大输出子序列分别是什么(输出一个即可!)
分析
那么这道题我的思路就是,找到最长的子序列让他们的相乘的积等于
k
∗
n
+
1
k*n+1
k∗n+1
(
k
为
任
意
常
数
)
(k为任意常数)
(k为任意常数)
那么由欧几里得定理,我们发现除了1以外,
n
n
n和
k
∗
n
+
1
k*n+1
k∗n+1是互质的,也就是
k
∗
n
+
1
k*n+1
k∗n+1分解不出来有关于
n
n
n的因子,所以说,我们就缩小了范围:从
1
1
1~
n
−
1
n-1
n−1所有的和n互质的数开始找就可以了。
现在让小于
n
−
1
n-1
n−1的所有和
n
n
n互质的数相乘,并对
n
n
n取模,得到的结果
w
w
w如果不是
1
1
1,就从答案中删掉
w
w
w这个元素。
简单证明一下~
w
w
w一定小于
n
n
n大于等于
1
1
1,因此由欧几里得算法:
因为
g
c
d
(
(
n
∗
k
+
w
)
,
n
)
=
1
gcd((n*k+w),n)=1
gcd((n∗k+w),n)=1,
所以
g
c
d
(
(
n
∗
k
+
w
)
gcd((n*k+w)
gcd((n∗k+w)%
n
,
n
)
=
g
c
d
(
w
,
n
)
=
1
n,n)=gcd(w,n)=1
n,n)=gcd(w,n)=1因此
w
w
w一定是小于
n
n
n且和
n
n
n互质的数,如果w=1,那么刚好就是我们的结果,如果w不等于1,那么只需要在所有小于n的与n互质的数中删掉这个就可以了。
代码:
#include<iostream>
using namespace std;
typedef long long ll;
int ans[1200000];
int gcd(int a,int b){
return b?gcd(b,a%b):a;
}
int main(){
int n;
int cnt=0;
cin>>n;
ll w=1;
for(int i=1;i<n;i++){
if(gcd(i,n)==1){
ans[++cnt]=i;
w=(w*(ll)i)%(ll)n;
}
}
if(w==1){
cout<<cnt<<endl;
for(int i=1;i<=cnt;i++)cout<<ans[i]<<' ';
}else {
cout<<cnt-1<<endl;
for(int i=1;i<=cnt;i++){
if(ans[i]==w)continue;
cout<<ans[i]<<" ";
}
}
}