正题
题目链接:https://www.luogu.com.cn/problem/CF1419E
题目大意
n n n的所有约数排成一个圈,求一个顺序使得相邻的互质的数最少。
解题思路
质因数分解后,我们考虑每个质因数之间填什么。对于两个质因数 a , b a,b a,b。显然 a ∗ b a*b a∗b也是 n n n的约数,也就是 a a a与 b b b之间必定有一个可以填进去的数。
显然对于每个质因数也是如此,一般的,我们对于分解出来的 p c p^c pc和 p ′ c ′ p'^{c'} p′c′我们可以在将 p k ( 1 ≤ k ≤ c ) p^k(1\leq k\leq c) pk(1≤k≤c)都填在一起,然后在之后填上具有 p p p和 p ′ p' p′因子的所有没有填过的约数。特别的, n n n要填在最后面(拼接第一个和最后一个质因子)。
然后对于只有两个不同的质因子 a , b a,b a,b的数,我们不难发现 a ∗ b = n a*b=n a∗b=n也就是 n n n没有办法填在最后,此时互质数为 1 1 1,其他都为 0 0 0
c o d e code code
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const ll N=2e5+10;
ll T,n,p[N],v[N],cnt;
void dfs(ll dep,ll x){
if(x==n||dep>cnt&&x==1)return;
if(dep>cnt){printf("%lld ",x);return;}
ll w=p[dep],z=1;
if(x==1){
for(ll i=1;i<=v[dep];i++)z*=w;
for(ll i=v[dep];i>=0;i--)
dfs(dep+1,x*z),z/=w;
}
else{
for(ll i=0;i<=v[dep];i++)
dfs(dep+1,x*z),z*=w;
}
}
int main()
{
scanf("%lld",&T);
while(T--){
scanf("%lld",&n);ll x=n,z=0;cnt=0;
for(ll i=2;i*i<=x;i++){
if(x%i==0){
p[++cnt]=i;
while(x%i==0)x/=i,v[cnt]++,z++;
}
}
if(x!=1){
bool flag=1;
for(ll i=1;i<=cnt;i++)
if(p[i]==x){flag=0;break;}
if(flag){
p[++cnt]=x;
v[cnt]++;z++;
}
}
dfs(1,1);
printf("%lld\n",n);
if(z==2&&cnt==2)printf("1\n");
else printf("0\n");
for(ll i=1;i<=cnt;i++)v[i]=0;
}
}