题目链接:https://www.luogu.com.cn/problem/P3599
这道题算是一道比较难的构造题,主要是第二种构造难度相对较高.
X=1的构造:
要让数列前缀和在模n意义下不同,我们发现如果n放在第i个,则有
,此时不满足各不相同,因此n必然放在第1个,即
. 同时,由于
,因此若n为奇数时(除1外),必然有
,故将该情况排除;考虑n为偶数时的构造:我们可以让前缀和依次为0,-1,1,-2,2…即可,此时各数即为0,-1,2,-3,4…即
,此时可以满足条件.
这组构造相对简单,我们主要考虑下面情况;
X=2的构造:
要让数列前缀积在模n意义下不同,n必然在最后,否则其之后的前缀积全为0. 若n为合数,则必然可分解为
,即必然会使出现二者之后前缀积全为0,排除此情况. 考虑n为质数时,我们不妨令前缀积依次为1,2,3,4…n,则
,由于n为质数,可通过费马小定理求其逆元(当然也可以线性递推).
注意:n=4要特判,因为4=2×2,无法分解为两不同小于4的数的乘积,可以给出构造。
两种情况n=1都直接输出“2 1”即可。
代码实现
#include<bits/stdc++.h>
using namespace std;
#define ll long long//记得开long long,不然快速幂会爆int
ll const N=1e5+10;
ll X,T,n;
namespace locax{
inline ll check(ll n){
for(ll i=2;i*i<=n;i++){
if(n%i==0)return 1;
}
return 0;
}
inline ll qukpow(ll a,ll b){
if(b==1)return a;
ll res=qukpow(a,b/2);
if(b&1)return (((res*res)%n)*a)%n;
else return (res*res)%n;
}
inline void solve1(ll n){
if(n==1){
cout<<"2 1\n";return;
}
if(n&1){
cout<<"0\n";return;
}
cout<<"2 ";
for(ll i=1;i<=n;i++){
if(i&1)cout<<n+1-i<<' ';
else cout<<i-1<<' ';
}
cout<<'\n';
}
inline void solve2(ll n){
if(n==1){
cout<<"2 1\n";return;
}
if(n==4){
cout<<"2 1 3 2 4\n";
return;
}
if(check(n)){
cout<<"0\n";
return;
}
cout<<"2 1 ";
for(ll i=2;i<n;i++){
cout<<(i*qukpow(i-1,n-2))%n<<' ';
}
cout<<n<<'\n';
}
}
int main(){
cin>>X>>T;
if(X==1){
while(T--){
cin>>n;locax::solve1(n);
}
}
else{
while(T--){
cin>>n;locax::solve2(n);
}
}
return 0;
}
1323

被折叠的 条评论
为什么被折叠?



