CF1514C Product 1 Modulo N (数论基础+思维)

54 篇文章 0 订阅
42 篇文章 1 订阅

题目传送门
参考大佬博客
本蒟蒻被fst的自闭场~~

题意

这个题目的意思就是什么呢?
给你一个数 n n n,现在让你找到 1 1 1~ n − 1 n-1 n1的最长子序列(非 l i s lis lis),子序列全部元素相乘 m o d n mod n modn等于 1 1 1,请你先输出长度,然后从小到大输出子序列分别是什么(输出一个即可!)

分析

那么这道题我的思路就是,找到最长的子序列让他们的相乘的积等于 k ∗ n + 1 k*n+1 kn+1 ( k 为 任 意 常 数 ) (k为任意常数) (k
那么由欧几里得定理,我们发现除了1以外, n n n k ∗ n + 1 k*n+1 kn+1是互质的,也就是 k ∗ n + 1 k*n+1 kn+1分解不出来有关于 n n n的因子,所以说,我们就缩小了范围:从 1 1 1~ n − 1 n-1 n1所有的和n互质的数开始找就可以了。
现在让小于 n − 1 n-1 n1的所有和 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((nk+w),n)=1
所以 g c d ( ( n ∗ k + w ) gcd((n*k+w) gcd(nk+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]<<" ";
		}
	}
}
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值