D e s c r i p t i o n Description Description
将n个人按n的所有约数d分成d种情况,每种情况有n/d个环,第一环的分布为1,d+1,2d+1…n-d+1,第二个环为2,d+2,2d+2…n-d+2,第d个环为d,2d,3d…n
对于一个点而言,它在每一种情况内的相邻点与这个点的编号都不能跟一样
给出n,请求出n个点的编号
I n p u t Input Input
一行,一个整数n。
O u t p u t Output Output
若有解,输出一行n 个字符。第i 个字符表示第i 号演员衣服的颜色,用小写英文字母表示。若有多种方案,请输出字典序最小的方案。
若无解,你得给家属留些话,输出"Impossible" 。
S a m p l e Sample Sample I n p u t Input Input
7
S a m p l e Sample Sample O u t p u t Output Output
abababc
H i n t Hint Hint
2 <= n <= 300000.
T r a i n Train Train o f of of T h o u g h t Thought Thought
找出所有的约数(除了它本身),枚举每一个点,再枚举每一种情况,记录邻点的编号,在26个编号中排除
C o d e Code Code
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
int n,tot,s[30005],a[300005],p[35];
int main()
{
freopen("arilang.in","r",stdin);
freopen("arilang.out","w",stdout);
scanf("%d",&n);
for (int i=1; i<n; ++i)
if (n%i==0) s[++tot]=i; //求出约数
a[1]=1; p[1]=true;
for (int i=2; i<=n; ++i)
{
for (int j=1; j<=tot; ++j)
p[a[(i+s[j]-1)%n+1]]=p[a[(i+n-s[j])%n]]=1;//相邻的两个点
for (int j=1; j<=26; ++j)
if (!p[j]) {
a[i]=j; break;//选编号
}
if (!a[i]) {
printf("Impossible");
return 0;
}//若没有编号可选,自然就是不可行
memset(p,0,sizeof(p));
}
for (int i=1; i<=n; ++i)
printf("%c",a[i]+96);
}