题意:给定一个素数p,用1,2,。。。p-1,进行排序,排序的序列必须符合第(x+1)位=第x位2%p,或者第(x+1)位=第x位3%p,请你构造这样一个序列。
思路:
(1)dfs递归来找,因为第一位肯定是1,之后的2~p-1位,有两种情况,2或者3,所以分别来找,然后回溯。递归出口一个是两种情况都不满足,所以往回来回溯,另一个是,计数达到了p-1位的时候,就证明已经达到的一个序列,然后退出。
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+9;
int a[N];
bool vis[N];
int f;int p;
void dfs(int x,int cnt)//数值,步数
{
if(cnt==p-1){//如果步数达到了p-1位,就退出
f=1;//标记,如果有符合的序列就输出
for(int i=1;i<=cnt;i++){
if(i!=cnt)
printf("%d ",a[i]);
else
printf("%d\n",a[i]);
}
return ;
}
int q=x*2%p;//*2的情况
int qq=x*3%p;//*3的情况
if(q>=1&&q<=p-1&&vis[q]==0){//范围判断,是否被用过
vis[q]=1;a[cnt+1]=q;//标记下来,cnt+1就是下一位
dfs(q,cnt+1);//去找下一位
vis[q]=0;//回溯时标记清空
}
else if(qq>=1&&qq<=p-1&&vis[qq]==0){
vis[qq]=1;a[cnt+1]=qq;
dfs(qq,cnt+1);
vis[qq]=0;
}
return ;//两种情况都不可以,就回溯递归出口
}
int main ()
{
int t;scanf("%d",&t);
while(t--){
memset(a,0,sizeof(a));
memset(vis,0,sizeof(vis));//初始化
scanf("%d",&p);
vis[1]=1;a[1]=1;f=0;
dfs(1,1);//dfs来找
if(f==0)
printf("-1\n");//如果没有合适的,就输出-1
}
return 0;
}
(2)分析下来,有一种构造规律,可以用2,就先2,2使不了,在进行3,如果两者都不行,就-1了。
代码:
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+9;
int a[N];
bool vis[N];
int main ()
{
int t;scanf("%d",&t);
while(t--){
memset(a,0,sizeof(a));
memset(vis,0,sizeof(vis));//初始化
int p;scanf("%d",&p);
int k=0;a[++k]=1;vis[1]=1;
int f=0;
for(int i=2;i<=p-1;i++){//有2~p-1位数字
int q=2*a[k]%p;//先*2来判断
if(q>=1&&q<=p-1&&vis[q]==0){
vis[q]=1;a[++k]=q;continue;//如果有,就继续,不用找*3
}
int qq=3*a[k]%p;//之后*3判断
if(qq>=1&&qq<=p-1&&vis[qq]==0){
vis[qq]=1;a[++k]=qq;
}
else{
f=1;break;//如果*2,*3都找不到了,就退出,输出-1
}
}
if(f==1){
cout<<"-1"<<endl;
}
else{
for(int i=1;i<=k;i++){//输出答案
if(i!=k) printf("%d ",a[i]);
else printf("%d\n",a[i]);
}
}
}
return 0;
}