题意:
给定 n n n,问 [ 1 , n ) [1,n) [1,n)中至多可以取哪些数使得这些数的乘积模 n n n等于 1 1 1
数据范围: 1 ≤ n ≤ 1 0 5 1\leq n\leq 10^5 1≤n≤105
题解:
考虑最后的乘积一定是 k n + 1 , k ≥ 0 kn+1,k\geq0 kn+1,k≥0
则有 g c d ( k n + 1 , n ) = g c d ( n , 1 ) = 1 gcd(kn+1,n)=gcd(n,1)=1 gcd(kn+1,n)=gcd(n,1)=1
因此选择的任意一个数都必须与 n n n互质。
如果所有选择的数的乘积模 n n n的值 p r o d prod prod为 1 1 1,则直接输出
否则将 p r o d prod prod这个数删去后,再输出剩余的数即可。
证明若 p r o d prod prod不为 1 1 1,则 p r o d prod prod一定与 n n n互质:
实际结果为: m u l = k n + p r o d , k ≥ 0 mul=kn+prod,k\geq0 mul=kn+prod,k≥0
则有 g c d ( m u l , n ) = g c d ( k n + p r o d , n ) = g c d ( p r o d , n ) gcd(mul,n)=gcd(kn+prod,n)=gcd(prod,n) gcd(mul,n)=gcd(kn+prod,n)=gcd(prod,n)
可以知道的是, m u l mul mul由所有的与 n n n互质的数相乘而来,因此 g c d ( m u l , n ) = 1 gcd(mul,n)=1 gcd(mul,n)=1,因此 g c d ( p r o d , n ) = 1 gcd(prod,n)=1 gcd(prod,n)=1,故 p r o d prod prod一定是被选择的数。
代码:
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
int st[N], ans[N], g;
int n, v;
int gcd(int a, int b) {
return b == 0 ? a : gcd(b, a % b);
}
int main()
{
scanf("%d", &n);
v = 1;
for(int i = 1; i < n; ++i)
if(gcd(i, n) == 1) {
v = 1ll * v * i % n;
st[i] = 1;
}
if(v != 1) st[v] = 0;
for(int i = 1; i < n; ++i)
if(st[i]) ans[++g] = i;
printf("%d\n", g);
for(int i = 1; i <= g; ++i)
printf("%d%c", ans[i], " \n"[i == g]);
return 0;
}