首先考虑任务一。
注意到前缀和互不相同 \(\iff\) 不存在一段区间 \([l,r](l>1)\) ,使其和为 \(0\)。
因此,\(n\) 应当放在第一个。考虑到剩余数总和为 \(\frac{n(n-1)}{2}\),若 \(2\not \mid n\),则 \(\frac{n(n-1)}{2}\equiv 0 \pmod n\),就不行。
对于 \(2\mid n\) 的情况,考虑构造前缀和为 \(0,1,-1,2,-2\cdots\) 的数,即形如 \(n,1,n-2,3,n-4,\cdots\) 的排列。
再考虑任务二。
注意到 \(n\equiv 0 \pmod n\),故 \(n\) 必须放在最后。由于模意义下的乘法运算大部分要求模数为质数。可以从这个方面思考。
可以发现,\(\forall n>4\) 且 \(n\) 为合数,都不满足题意。原因在于必定 \(\exists p<q<n,n\mid pq\)。
对于质数的话,我们可以用逆元!容易想出构造 \(1,\frac 21,\frac 32,\frac 43,\cdots\) 的数,显然互不相同。
对于特例 \(4\),考虑直接构造 \(1,3,2,4\)
#include <cstdio>
#include <cctype>
#include <algorithm>
using namespace std;
char buf[1<<21],*p1=buf,*p2=buf;
#define GetC() ((p1==p2)&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
struct Ios{}io;
template <typename _tp>
Ios &operator >>(Ios &in,_tp &x){
x=0;int w=0;char c=GetC();
for(;!isdigit(c);w|=c=='-',c=GetC());
for(;isdigit(c);x=x*10+(c^'0'),c=GetC());
if(w) x=-x;
return in;
}
void solve1(int n){
if((n&1)&&n!=1){
puts("0");
return ;
}
printf("2 ");
for(int i=1;i<=n;++i){
if(i&1) printf("%d ",n-i+1);
else printf("%d ",i-1);
}
puts("");
}
const int N=1e5+5;
int inv[N];
void solve2(int n){
if(n==4){
puts("2 1 3 2 4");
return ;
}
for(int i=2;i*i<=n;++i){
if(n%i==0){
puts("0");
return ;
}
}
printf("2 ");
inv[1]=1;
for(int i=2;i<=n;++i){
inv[i]=1ll*(n-n/i)*inv[n%i]%n;
}
for(int i=1;i<=n;++i){
if(i==1||i==n){
printf("%d ",i);
}
else printf("%lld ",1ll*i*inv[i-1]%n);
}
}
int main(){
int x,T;io>>x>>T;
while(T--){
int n;io>>n;
if(x==1){
solve1(n);
}
else{
solve2(n);
}
}
return 0;
}
标签:include,frac,int,GetC,cdots,Construction,return,P3599,Koishi
From: https://www.cnblogs.com/pref-ctrl27/p/16975020.html