Codeforces Round #716 (Div. 2) C. Product 1 Modulo N

C. Product 1 Modulo N
time limit per test1 second
memory limit per test256 megabytes
inputstandard input
outputstandard output
Now you get Baby Ehab’s first words: “Given an integer n, find the longest subsequence of [1,2,…,n−1] whose product is 1 modulo n.” Please solve the problem.

A sequence b is a subsequence of an array a if b can be obtained from a by deleting some (possibly all) elements. The product of an empty subsequence is equal to 1.

Input
The only line contains the integer n (2≤n≤105).

Output
The first line should contain a single integer, the length of the longest subsequence.

The second line should contain the elements of the subsequence, in increasing order.

If there are multiple solutions, you can print any.

Examples
inputCopy
5
outputCopy
3
1 2 3
inputCopy
8
outputCopy
4
1 3 5 7
Note
In the first example, the product of the elements is 6 which is congruent to 1 modulo 5. The only longer subsequence is [1,2,3,4]. Its product is 24 which is congruent to 4 modulo 5. Hence, the answer is [1,2,3].

官方思路:
首先要观察到子序列不能包含任何不与n互素的元素。 为什么? 因为这样它的乘积就不会与n互质,所以当以n为模时,它就不能为1。换句话说,gcd(prod mod n,n)= gcd(prod,n)≠1。 现在,让我们取小于n的所有元素并对其进行互素,让我们看一下它们对乘积n求模的结果。 称它为p。 如果p为1,则可以采用所有这些元素。 否则,除了p外,您都应该全部使用它们。 它属于它们,因为p与n互质。

我的想法:
首先,取模为1想到没有共同因子
所以子序列不能包含任何不与n互素的元素
add:如果a,b均不与c互质,则a*b必不与c互质,必也在内
则我们之后通过那些乘积取余n,可以得到1~n-1的数d
答案要求是1,那么我们让刚刚的乘积除以d就可以了对不对
之所以能整除d,是因为d在与n互素的数中,
因为有gcd(prod mod n,n)= gcd(prod,n)
而他们的乘积与n互素,即 gcd(prod,n)=1
因为prod的各素因子n都没有,所以prod是与n互素的
连起来了呼

总结:

  • 公式:gcd(a mod b,b)= gcd(a,b)熟悉,也是辗转相除法嘛
  1. 要取模为1,1和b就互素,(必要条件是)a mod b 与 b 互素 ,则 a 与 b 互素。
  2. 取了互素的,a为所有与b互素之乘,则a 与 b 互素,则a mod b 与 b 互素,
  3. 但是c=a mod b 是与 b 互素的其中之一,不过c这个之一包括在所有与b互素之内,所以我们在所有与b互素之乘中整除了c就可以。

如何想到:
∏ \prod 取模为1,即 ∏ \prod mod n =1,有一条 ∏ \prod mod n 与 n 互素的性质
扩大范围扩充性质,之后 ∏ \prod mod n是什么(已经看出是n的一个素数因子),如果这在 ∏ \prod 内,除回来就可以了,这挺可能的
∏ \prod mod n 与 n 互素,即 ∏ \prod 与 n 互素,尽量长的话,即 ∏ \prod 是n所有的素因子相乘,保证了互素
开始已经有了 ∏ \prod mod n 与 n 互素,现在出来了一个互素的结果,一定在 ∏ \prod ,n的素因子相乘内。

值得注意的知识点:
有一个count(p1,p2,a)函数,计算从p1到p2有几个a

#include <bits/stdc++.h>
using namespace std;
bool ok[100005];
int main()
{
	int n;
	scanf("%d",&n);
	long long prod=1;
	for (int i=1;i<n;i++)
	{
		if (__gcd(n,i)==1)
		{
			ok[i]=1;
			prod=(prod*i)%n;
		}
	}
	if (prod!=1)
	ok[prod]=0;
	printf("%d\n",count(ok+1,ok+n,1));
	for (int i=1;i<n;i++)
	{
		if (ok[i])
		printf("%d ",i);
	}
}

  • 4
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值