/*
http://acm.hdu.edu.cn/showproblem.php?pid=4259
题意是:给定一个排列和一个特定的置换,最后问你最少要多少步置换才能回到原来的状态
解题思路就是:找出置换中的各个置换回路的长度,答案就是各个置换回路的最小公倍数
举个例子:
排列:1 2 3 4 5 6
置换:2 3 5 4 1 6
那么第一个置换回路是1 2 3 5,长度为4,第二个置换回路是 6,长度为1;
所以答案就是4和1的最小公倍数4
而这题的关键就是我们要找到这个置换,也就是初始排列第一次被转换后的结果
假设n为10,k为3;那么这题的初始排列就是1,2,3,4,5,6,7,8,9,10
第一次转换后就是10,7,4,1,8,5,2,9,6,3
第一个回路为:1,10,3,4,长度为4
第二个回路为:2,7,长度为2
第三个回路为:5,8,9,6,长度为4
所以答案就是4,4,2的最小公倍数4
代码如下:
*/
#include<stdio.h> #include<string.h> int vis[810],std[810],num[810][810]; __int64 gcd(__int64 a,__int64 b) { return b==0?a:gcd(b,a%b); } __int64 solve(int n,int k) { int p,i,j,cnt; __int64 sum=1,tem,d; for(i=1;i<=k;i++) { j=i; cnt=0; while(j<=n) { num[i][++cnt]=j; j+=k; } num[i][0]=cnt; } cnt=0; for(i=1;i<=k;i++) { for(j=num[i][0];j>=1;j--) std[++cnt]=num[i][j]; } memset(vis,0,sizeof(vis)); for(i=1;i<=n;i++) { if(!vis[i]) { tem=1; vis[i]=1; p=i; while(std[p]!=i) ++tem,p=std[p],vis[p]=1; d=gcd(sum,tem); sum/=d; sum*=tem; } } return sum; } int main() { int n,k; while(scanf("%d%d",&n,&k),n+k) printf("%I64d\n",solve(n,k)); return 0; }