题意:Task1:试判断能否构造并构造一个长度为n的排列,满足其n个前缀和在模nn的意义下互不相同
Task2:试判断能否构造并构造一个长度为n的排列,满足其n个前缀积在模n的意义下互不相同
题解: 不妨写个暴力观察一下规律。
对于T1 n一定是在排列的最前面,因为任意数+n%n的答案一定一样
奇数都没有解,对于偶数尝试构造数列(可以通过dfs搜出几个答案很容易看出这一组数列)
n
,
1
,
n
−
2
,
3
,
n
−
4....
n,1,n-2,3,n-4....
n,1,n−2,3,n−4....
这个数列很显然是满足条件的
T2:简单分析可得出n必须放在末尾,1必须放在首位
n为质数特例有1,4
同样用暴力dfs观察规律,对于前缀积模n满足条件:
1
,
2
,
3
,
4
,
.
.
.
.
n
−
1
,
0
1,2,3,4,....n-1,0
1,2,3,4,....n−1,0
有等式:
2
∗
a
n
s
(
2
)
≡
3
(
m
o
d
n
)
2*ans(2)\equiv3(modn)
2∗ans(2)≡3(modn)
a
n
s
(
x
)
≡
x
+
1
x
(
m
o
d
n
)
ans(x)\equiv\frac{x+1}{x}(mod n)
ans(x)≡xx+1(modn)
所以就是构造模n下的序列:
1
,
2
1
,
3
2
.
.
.
.
n
n
−
1
1,\frac{2}{1},\frac{3}{2}....\frac{n}{n-1}
1,12,23....n−1n
由于n为质数(除1,4之外)所以用费马小定理求逆元就行了
#include<bits/stdc++.h>
#define ll long long
const int MAXN=1e6+10;
const int M=1e6;
using namespace std;
bool vis[MAXN];
int ans[MAXN];
int sum[110];
int flag[110];
int T,X,num;
ll prime[MAXN],n;
bool isPrime[MAXN];
ll pow_mod(ll a,ll b,ll MOD){
int ans=1;
while(b){
if(b&1) ans=ans*a%MOD;
b>>=1;a=a*a%MOD;
}
return ans;
}
void dfs(int num){
if(num==n+1){
memset(flag,0,sizeof flag);
sum[0]=1;
for(int i=1;i<=n;i++){
sum[i]=sum[i-1]*ans[i]%n;
flag[sum[i]%n]++;
}
for(int i=0;i<n;i++){
if(flag[i]!=1) return ;
}
cout<<endl;
for(int i=1;i<=n;i++) cout<<ans[i]<<" ";
cout<<endl;
for(int i=1;i<=n;i++) cout<<sum[i]<<" ";
cout<<endl;
return ;
}
for(int i=1;i<=n;i++){
if(!vis[i]){
ans[num]=i;vis[i]=1;
dfs(num+1);
ans[num]=0;vis[i]=0;
}
}
}
void init(int x){
num=0;memset(vis,0,sizeof vis);
for(int i=2;i<=x;i++){
if(!vis[i]) prime[++num]=i;
for(int j=1;prime[j]*i<=x && j<=num;j++){
vis[i*prime[j]]=1;
if(!(i%prime[j])) break;
}
}
memset(isPrime,0,sizeof isPrime);
for(int i=1;i<=num;i++) isPrime[prime[i]]=1;
}
int main(){
ios::sync_with_stdio(false);
init(1e6);
cin>>X>>T;
if(X==1){
while(T--){
cin>>n;
if((n&1)&&(n^1)) cout<<"0"<<endl;
else {
cout<<"2 ";
ans[1]=n;
ans[2]=1;
for(int i=4;i<=n;i+=2) ans[i]=ans[i-2]+2;
for(int i=3;i<=n;i+=2) ans[i]=ans[i-2]-2;
for(int i=1;i<=n;i++) cout<<ans[i]<<" ";
cout<<endl;
}
}
}else{
while(T--){
cin>>n;
if(n==1 || n==4 || isPrime[n]) {
cout<<"2 ";
if(n==1) {
cout<<"1"<<endl;continue;
}
if(n==4) {
cout<<"1 3 2 4"<<endl;continue;
}
ans[1]=1;ans[n]=n;
for(int i=2;i<=n-1;i++) ans[i]=(i%n)*(pow_mod(i-1,n-2,n)%n)%n;
for(int i=1;i<=n;i++) cout<<ans[i]<<" ";
cout<<endl;
}else cout<<"0"<<endl;
}
}
return 0;
}