正题
题目链接:https://www.luogu.com.cn/problem/P3599
题目大意
构造一个nnn的排列,要求满足其中一个给定的要求
- 对于每个前缀和在模nnn意义下不同
- 对于每个前缀积在模nnn意义下不同
解题思路
对于加法,显然nnn要填在第一位,那么这一位的前缀和就是000了。并且如果nnn是奇数那么有(∑i=1ni)%n=0(\sum_{i=1}^ni)\%n=0(∑i=1ni)%n=0所以nnn不能是奇数。对于nnn是偶数的情况,我们可以将一个数iii在模nnn意义下视为−(n−i)-(n-i)−(n−i)。所以我们可以构造一个波动序列也就是n,1,−2,3,−4,5,−6...n,1,-2,3,-4,5,-6...n,1,−2,3,−4,5,−6...
对于乘法,nnn要填在最后,111要填在第一位,然后如果nnn是一个合数,那么有(∏i=1ni)%n=0(\prod_{i=1}^ni)\%n=0(∏i=1ni)%n=0也就是有两个000,所以无解。那么nnn是一个质数的情况,我们知道在模nnn意义下对于每个数都有一个不同的逆元,考虑构建一个ai=1i−1∗ia_i=\frac{1}{i-1}*iai=i−11∗i的序列,这样si=is_i=isi=i。
如何证明aia_iai在模nnn意义下各不相同,设ai=aj=ka_i=a_j=kai=aj=k那么有(i−1)k%n=i,(j−1)k%n=j(i-1)k\%n=i,(j-1)k\%n=j(i−1)k%n=i,(j−1)k%n=j
⇒(i−j)k%n=(i−j)\Rightarrow (i-j)k\%n=(i-j)⇒(i−j)k%n=(i−j)
要求k≠1k\neq 1k=1所以不成立。
codecodecode
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
ll idx,n,T;
ll power(ll x,ll b){ll ans=1;while(b){if(b&1)ans=ans*x%n;x=x*x%n;b>>=1;}return ans;
}
int main()
{scanf("%lld%lld",&idx,&T);while(T--){scanf("%lld",&n);if(idx==1){if(n==1)printf("2 1");else if(n&1)printf("0");else {printf("2 ");ll k=0;for(ll i=1;i<=n;i++){if(i&1)printf("%lld ",n-k);else printf("%lld ",k);k++;}}}else{bool flag=0;if(n==1)printf("2 1");else if(n==4)printf("2 1 3 2 4");else{for(ll i=2;i*i<=n;i++)if(n%i==0){flag=1;break;}if(flag){printf("0\n");continue;}printf("2 1 ");ll last=1;for(ll i=2;i<n;i++){ll k=power(last,n-2)*i%n;last=last*k%n;printf("%lld ",k);}printf("%lld",n);}}putchar('\n');}
}