Problem:
問題 G : Perm Query

問題文

\{1,  2,  … ,  N\}の順列 (p(1),  p(2),  … ,  p(n)) が与えられる．
(l_i,  r_i) からなるクエリが Q 個与えられるので，各クエリに対して以下の擬似コードによる処理結果を出力せよ．

ret   :=   0, (x(1),  x(2),  … ,  x(N))  :=  (1,  2,  … ,  N) とおく．

各i   ∈ \{1,   2,  … ,   N\} について y(i) := p(x(i)) とする．

各i   ∈ \{1,   2,  … ,   N\} について x(i)   =  y(i)とする．

ret   :=  ret + x(l_i) + x(l_i+1) + …  + x(r_i)

もし (x(l_i),  x(l_i+1),  … ,  x(r_i)) = (l_i,  l_i+1,  … ,  r_i) なら (ret   mod10^9+7) を出力して終了する．そうでないなら 2 行目に戻る．

入力形式

入力は以下の形式で与えられる

N Q
p(1) p(2) ... p(N)
l_0 r_0
...
l_{Q-1} r_{Q-1}

出力形式

各クエリに対する出力を1行ずつ出力せよ．

制約

1 ≤ N ≤ 10^5

1 ≤ Q ≤ 10^4

(p_1,  p_2,  … ,  p_N) は (1,  2,  … ,  N) の順列になっている．

各 i に対して，ある 1 ≤ k ≤ 40 が存在して，p^k(i)=i となる．ここで，p^k(i) は p(p(p(… p(i)… ))) で p が k 回現れるもの．

1 ≤ l_i   ≤   r_i   ≤ N

入出力例

入力例 1

5 2
5 1 2 3 4
1 1
2 4

出力例 1

15
45

擬似コード中の順列(x(1),   x(2),   … ,  x(N))は以下のように変化する．

1 2 3 4 5
5 1 2 3 4
4 5 1 2 3
3 4 5 1 2
2 3 4 5 1
1 2 3 4 5

入力例 2

10 5
3 1 2 5 4 10 6 7 9 8
1 10
1 5
3 3
5 10
9 10

出力例 2

660
90
6
178
67

Solution in Ruby (judge verdict: Wrong Answer)

def gcd(m, n)
	if m < n 
		gcd(n, m)
	elsif n == 0
		m
	else
		gcd(n, m % n)
	end 
end

def compute_lcm(m, n)
	m * n / gcd(m, n)
end

class Array
	def accum
		ac = Array.new(size + 1)
		ac[0] = 0
		(1..size).each do |i|
			ac[i] = ac[i-1] + self[i-1]
		end
		ac
	end
end

class LCMTree
	def initialize(a, l, r)
		@l, @r = l, r
		if l == r
			@lcm = a[l]
			@left = @right= nil
		else
			@left= LCMTree.new(a, l, (l+r)/2)
			@right= LCMTree.new(a, (l+r)/2+1, r)
			@lcm = compute_lcm(@left.lcm, @right.lcm)
		end
	end

	def lcm(l = @l, r = @r)
		if l == @l && r == @r
			@lcm
		elsif r <= @left.r
			@left.lcm(l, r)
		elsif @right.l <= l
			@right.lcm(l, r)
		else
			compute_lcm(@left.lcm(l, @left.r), @right.lcm(@right.l, r))
		end
	end

	attr_reader :l, :r
end

n, q = gets.split.map(&:to_i)
perm = [nil] + gets.split.map(&:to_i)

cycle = Array.new(n+1)
add_per_perm = Array.new(n+1)
(1..n).each do |x0|
	k = 1
	x = perm[x0]
	add_per_perm[x0] = x
	until x == x0
		k += 1
		x = perm[x]
		add_per_perm[x0] += x
	end
	cycle[x0] = k
	add_per_perm[x0] /= k.to_f
end
add_per_perm.shift
accum = add_per_perm.accum

t = LCMTree.new(cycle, 1, n)

q.times do
	l, r = gets.split.map(&:to_i)
	k = t.lcm(l, r)
	add = accum[r] - accum[l-1]
	p (add * k).to_i % 1000000007
end