[CF487C]Prefix Product Sequence

做题时间:2022.7.21

\(【题目描述】\)

给定整数 \(N(1\leq N\leq 10^5)\) ,求出任意一种满足所有前缀积构成 \(N\) 的一个完全剩余系的排列(即一个排列的前缀积\(mod\) \(n\) 结果两两不同),若不存在输出 \(NO\)

\(【输入格式】\)

一行一个整数 \(N\)

\(【输出格式】\)

第一行一个 \(YES\)\(NO\) 表示是否存在
接下来 \(N\) 行每行一个数,表示答案的排列

\(【考点】\)

逆元、构造

\(【做法】\)

先考虑什么时候有解。若 \(n\) 有超过两个不为 \(n\) 的不相同的因子,那么这两个因子相乘会使得后面所有的前缀积都变成0,因此不行。符合要求的仅有全体质数和 \(4\)

然后考虑构造,首先1只能放在第一个位置,同时 \(n\) 只能放在最后一个位置。

由于是在模 \(n\) 意义下的,因此可以考虑一下逆元(? 这样就有一个很无脑灵活的思路,即构造一个序列:

\[\large\mathit{1,\frac{2}{1},\frac{3}{2},\frac{4}{3},\frac{5}{4},\cdots ,n} \]

可以看出这个序列在模 \(n\) 意义下即是 \(n\) 的一个排列,且前缀积在模 \(n\) 意义下是 \(n\) 的一个完全系

在实现的时候特判一下1和4的情况即可。

然后就这么无脑地做完了,虽然有一种原根的正常解法但我也不会

\(【代码】\)

#include<cstdio>
#include<iomanip>
using namespace std;
typedef long long ll;
const int N=1e5+50;
ll a[N],Inv[N],n;
bool Check(int n)
{
//	if(n==1) return false;
	for(ll i=2;i*i<=n;i++){
		if(n%i==0) return false;
	}
	return true;
}
int main(){
	scanf("%d",&n);
	if(n!=4&&!Check(n)){
		printf("NO\n");
		return 0;
	}
	printf("YES\n1\n");
	if(n==4){
		printf("3\n2\n4\n");
		return 0;
	}
	if(n==1) return 0;
	Inv[0]=Inv[1]=1;
	for(int i=2;i<=n;i++) Inv[i]=(n-n/i)*Inv[n%i]%n;
	
	for(int i=2;i<=n-1;i++) printf("%lld\n",i*Inv[i-1]%n);
	printf("%d\n",n);
	return 0;
}
posted @ 2022-07-21 14:42  lxzy  阅读(37)  评论(0)    收藏  举报