数列变换,先预处理每一个位置的下一个位置,然后找出每一个位置的循环节求最小公倍数。
ACcode:
#include<cstdio>
#include<cstring>
#include<cstdlib>
typedef long long LL;
const int NS=810;
LL res[NS][NS];
int next[NS];
int num[NS];
LL gcd(LL a,LL b)
{
return b? gcd(b,a%b):a;
}
LL solve(int n,int k)
{
int t;
LL ans=1,m=1;
for (int j,i=1;i<=k;i++)
{
j=n/k*k+i;
if (j>n) j-=k;
for (;j>0;j-=k)
next[j]=m++;
}
memset(num,0,sizeof(num));
for (int i=1;i<=n;i++)
{
if (num[i]) continue;
m=1,t=next[i],num[i]++;
while (t!=i) num[t]++,t=next[t],m++;
ans=ans/gcd(m,ans)*m;
}
return ans;
}
int main()
{
int n,k;
for (int i=1;i<=800;i++)
for (int j=1;j<=800;j++)
res[i][j]=i>j?-1:1;
while (~scanf("%d%d",&n,&k)&&(n+k))
{
if (n<=k) res[n][k]=1;
if (res[n][k]==-1)
res[n][k]=solve(n,k);
printf("%I64d\n",res[n][k]);
}
return 0;
}
1223

被折叠的 条评论
为什么被折叠?



