构造 的排列,使得其前缀积在 意义下两两不同。
。
首先显然 放最前面, 放最后面。并且若 且 为合数就一定无解,因为 的所有因数都会出现,所以前缀积至少会出现两个 。
那么特判掉 的情况,考虑 且 为质数的情况。
发现原排列似乎不是很好处理,于是考虑前缀积序列,考虑构造形如 这样的前缀积序列,显然原序列一定是这个序列的差商,即 这样的。容易发现中间的分数显然和首尾两个数不同,并且中间的分数都是形如 这样的,统统减去 之后变成了 ,也两两不同,所以整个序列是排列,这样构造合法。
代码如下:
#include <iostream>
#include <cstdio>
using namespace std;
const int S=100005;
int n,ans[S];
inline bool chk(int n)
{
for(int i=2;i<=n-1;i++) if(n%i==0) return false;
return true;
}
inline int qpow(int x,int y)
{
int res=1;
for(;y>0;y>>=1,x=1ll*x*x%n) res=(y&1)?1ll*res*x%n:res;
return res;
}
int main()
{
scanf("%d",&n);
if(n==1) puts("YES\n1");
else if(n==2) puts("YES\n1\n2");
else if(n==3) puts("YES\n1\n2\n3");
else if(n==4) puts("YES\n1\n3\n2\n4");
else if(!chk(n)) puts("NO");
else
{
ans[1]=1,ans[n]=n;
for(int i=2;i<=n-1;i++) ans[i]=1ll*i*qpow(i-1,n-2)%n;
puts("YES");
for(int i=1;i<=n;i++) printf("%d\n",ans[i]);
}
return 0;
}