[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;
}

浙公网安备 33010602011771号