题目描述
题解
该题极其符合人类思维逻辑,我们一般用两个字来形容这种题“水题”。
在草稿纸上画一下这个序列的样子
k
+
1
k
+
2
k
+
3
⋯
⋯
n
1
2
3
⋯
⋯
k
k+1\quad k+2\quad k+3\quad\cdots\cdots \quad n \quad 1\quad 2 \quad3\quad\cdots\cdots k
k+1k+2k+3⋯⋯n123⋯⋯k
我们把一个循环看成许多次跳跃,每次从第
i
i
i个位置跳到第
a
[
i
]
a[i]
a[i]个位置,规定方向向右。可以发现每一步的跳跃长度是相等的为
k
k
k,每一个循环独立,并且每一个循环的长度(称其为
c
n
t
cnt
cnt)也是相等的(并且在形式上是相同的)。(因为错位后的位置关系是没有改变的)
所以我们只需求出
c
n
t
cnt
cnt,答案为
n
/
c
n
t
n/cnt
n/cnt。
怎样求
c
n
t
cnt
cnt呢。对
70
%
70\%
70%的数据,我们可以暴力的模拟跳跃的过程,最坏情况是
O
(
n
)
O(n)
O(n)的。
对于全部数据(貌似更容易想到这个吧),可以想象跳跃的过程,每次跳
k
k
k这么长,在一个长度为
n
n
n的环上跳回原点,跳跃长度为
l
c
m
(
n
,
k
)
lcm(n,k)
lcm(n,k),所以
c
n
t
cnt
cnt等于跳跃步数为
l
c
m
(
n
,
k
)
/
k
lcm(n,k)/k
lcm(n,k)/k,
A
n
s
=
n
/
(
l
c
m
(
n
,
k
)
/
k
)
Ans=n/(lcm(n,k)/k)
Ans=n/(lcm(n,k)/k)
整理一下
A
n
s
=
(
n
∗
k
)
/
l
c
m
(
n
,
k
)
=
g
c
d
(
n
,
k
)
Ans=(n*k)/lcm(n,k)=gcd(n,k)
Ans=(n∗k)/lcm(n,k)=gcd(n,k)
代码
#include<cstdio>
#include<algorithm>
using namespace std;
const int MAXN=int(1e6+5);
#define int long long
int n,k;
int a[MAXN];
int gcd(int a,int b) {
return (b==0)?a:gcd(b,a%b);
}
signed main()
{
scanf("%lld%lld",&n,&k);
/*
for(int i=k+1;i<=n;i++)
a[i-k]=i;
for(int i=1;i<=k;i++)
a[n-k+i]=i;
int st=1,nw=1,cnt=0;
do {
cnt++;
nw=a[nw];
}while(st!=nw);
printf("%d\n",n/cnt);
*/
printf("%lld",gcd(n,k));
}
抱歉,之前被 l o n g l o n g long\ long long long搞了,就懒得改完了。
T h a n k s Thanks Thanks F o r For For R e a d i n g ! Reading! Reading!