这一次呢,题目要求让a[1]=x,a[n]=1,我们需要找到一个最小的序列使得每一个a[i]都可以被它的下标整除,没找到就是输出-1
我第一次是想着先让a[1]=x,a[n]=1,然后在中间一个一个的找它的下标的倍数,结果wa了
最后还是没有做出来!ε=(´ο`*)))唉
看来题解之后,才知道他们是这么做的(好想知道他们聪明的脑袋瓜子是怎么想出来的)
第一步是先判断n%x==0,如果不满足,那么就一定是输出-1
然后,找出所有n的因数(除了a[1]=x,a[n]=1,a[x]=n,其他的都让a[i]=i),
比如n=16,那么就有2,4,8,(不包括1和本身),x=2,那么我们可以把a[2]=4,a[4]=8,a[8]=16,a[16]=1(a[n]=1),一个这样的交换,这也是为什么我们要在前面判断n%x==0这一条件,这样的情况,刚好就是字典序最小的情况。
而且记得在交换的时候(swap(a[i],a[now],这个now是上一次的下标)也要记得判断是否满足a[i]%now等于0这一条件,因为我们也要保证交换了之后a[i]%i==0呀
比如n=36时,x=6,可以交换的就只有6,12,18,而不是2,3,4,6,9,12,18,如果是2,3,4,6,9,12,18,那么a[2]=3就这一个个就不符合条件了,所以还要判断上一次交换的下标和这一次的值是否可以整除
接下来就是看代码了
#include <iostream>
#include <stdlib.h>
#include <algorithm>
using namespace std;
const int maxn=2e5+10;
int t,n,x,ans[maxn];
void solve()
{
cin>>n>>x;
ans[1]=x,ans[n]=1;
for (int i=2;i<n;i++)
{
if (i==x) ans[i]=n;
else ans[i]=i;
}
if (n%x)
{
cout<<-1<<'\n';
return ;
}
if (n==x)
{
for (int i=1;i<=n;i++)
{
cout<<ans[i]<<" ";
}
cout<<'\n';
return ;
}
int now=x;
for (int i=x;i<n;i++)
{
if (n%i==0&&ans[i]%now==0)
{
swap(ans[i],ans[now]);
now=i;
}
}
for (int i=1;i<=n;i++)
{
cout<<ans[i]<<" ";
}
cout<<'\n';
return ;
}
int main ()
{
cin>>t;
while (t--)
{
solve();
}
system ("pause");
return 0;
}
标签:now,836,16,int,18,Codeforces,ans,Div,include
From: https://www.cnblogs.com/righting/p/16996620.html