Codeforces Round#716(div.2) (solved AB)
比赛链接 https://codeforces.com/contest/1514
C题
题目大意
给一个n,能否在数组[1,2,…,n-1]中找一个最长子序列,使序列乘积模n值为1
题解
第一、对n取模结果为1的数一定与n互质
选择的数只能是数组中与n互质的数,这样乘积才与n互质,那么先将数组中所有与n互质的数乘起来
第二、与n互质的数对n取模结果不一定为1
设乘积模n的结果为p,若p不为1,则从选择的数中将p移除
一句话就是“选择所有与n互质的数,乘积模n结果为p 若p不为1则从选择的数中移除p”
"p不为1时将p移除" 也就是说p一定落在了被选择的数中 为什么呢
数学地: a,b互质 a mod b 是否一定与b互质
证:
设c = a mod b
再设 b=md······① c=nd······② (d是b,c的一个公因数 m,n是各自的倍数)
下面若能证明d是a的因数,那么bc的公因数一定也是ab的公因数 而ab互质公因数为1 则bc公因数为1 则bc互质
c= a mod b 所以存在k使得 a=kb+c······③ 将①②带入③ a=kmd+nd=(km+n)d 即d是a的因数
结果不为1时,为什么将p移除 结果就为1了
数学地:小于n的所有质数乘积为s,p=s mod n 为什么当p不为1时 s/p mod n的结果一定为1
嗯…自己纠结了很久 然后发现其实是一个很明显的事情
s mod n=p 即 s除以n=k余p 由于s有因数p 那么k其实也是p的倍数 所以s/p=k/p余1 k/p是整数
(记得开long long)
#include <bits/stdc++.h>
#define int long long
using namespace std;
signed main(){
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
// freopen("in.txt","r",stdin);
int n;cin>>n;
vector<int> ok(n+1);
int p=1;
int cnt=0;
for(int i=1;i<n;i++){
if(__gcd(i,n)==1){
cnt++;
p=p*i%n;
ok[i]=1;
}
}
if(p!=1){
cnt--;
ok[p]=0;
}
cout<<cnt<<'\n';
for(int i=0;i<n;i++){
if(ok[i])cout<<i<<' ';
}
#define _ 0
return ~~(0^_^0);
}