 /**//*
題意:1,2 ,N這個(gè)序列,給出一個(gè)變換的序列next[],現(xiàn)不斷變換
求變換A到B次的,在范圍[C+1,N-D]的數(shù)等于原來位置的序列的個(gè)數(shù)
可以O(shè)(n)找出每個(gè)數(shù)的循環(huán)節(jié),dfs
然后總的周期 P = LCM(cycle[ C+1 ],…, cycle[ N-D ] )
然后答案就是solve(B) - solve(A-1)

題目應(yīng)該不算非常難,但我還是想不到,可能不熟悉了
*/
#include<cstdio>
#include<cstring>
#include<algorithm>

using namespace std;

const int MAXN = 500010;

int cycle[MAXN],next[MAXN];
int N;
long long period;

int dfs(int x ,int pos, int len)//O(n)找所有點(diǎn)的循環(huán)節(jié)
  {
if( x == pos && len > 0 )return len;
return cycle[x] = dfs( x ,next[pos] , len+1 );
}

long long gcd( long long a, long long b)
  {
return b ? gcd( b, a%b ) : a ;
}

inline long long lcm( long long &a, long long b )
  {
return a / gcd( a ,b ) * b;
}

long long solve(long long x)
  {
return ( x + period -1 ) / period;//上界要這樣子寫
//寫成(x-1)/p+1的話0的上界變?yōu)?了
}

int main()
  {
freopen( "in", "r", stdin);
long long A,B;
int C,D;
while( ~scanf("%d%lld%lld%d%d",&N,&A,&B,&C,&D) )
 {
C ++ ;
D = N - D;
for( int i=1; i<=N; i++ )
scanf( "%d", &next[i] );

memset( cycle, -1, sizeof( cycle ) );
for( int i=1; i<=N; i++ )
 {
if( cycle[i] == -1 ) dfs( i, i, 0 );
}
period = 1;
for( int i=C; i<=D ;i++ )
 {
period = lcm( period , cycle[i] );
 if(period > B) { period = B+1; break; }
}
printf("%lld\n", solve(B) - solve(A-1));
}
return 0;
}

|