CodeForces 906D Power Tower(欧拉降幂定理)

D. Power Tower

time limit per test:4.5 seconds

memory limit per test:256 megabytes

input:standard input

output:standard output

Priests of the Quetzalcoatl cult want to build a tower to represent a power of their god. Tower is usually made of power-charged rocks. It is built with the help of rare magic by levitating the current top of tower and adding rocks at its bottom. If top, which is built from k - 1 rocks, possesses power p and we want to add the rock charged with power wk then value of power of a new tower will be {wk}p.

Rocks are added from the last to the first. That is for sequence w1, ..., wm value of power will be

After tower is built, its power may be extremely large. But still priests want to get some information about it, namely they want to know a number called cumulative power which is the true value of power taken modulo m. Priests have n rocks numbered from 1 to n. They ask you to calculate which value of cumulative power will the tower possess if they will build it from rocks numbered l, l + 1, ..., r.

Input

First line of input contains two integers n (1 ≤ n ≤ 105) and m (1 ≤ m ≤ 109).

Second line of input contains n integers wk (1 ≤ wk ≤ 109) which is the power of rocks that priests have.

Third line of input contains single integer q (1 ≤ q ≤ 105) which is amount of queries from priests to you.

kth of next q lines contains two integers lk and rk (1 ≤ lk ≤ rk ≤ n).

Output

Output q integers. k-th of them must be the amount of cumulative power the tower will have if is built from rocks lk, lk + 1, ..., rk.

Example

Input

6 1000000000
1 2 2 3 3 3
8
1 1
1 6
2 2
2 3
2 4
4 4
4 5
4 6

Output

1
1
2
4
256
3
27
597484987

Note

3^27 = 7625597484987

 

 

        一道定理题。

        大致题意:有N个数字,然后给你q个区间,要你求每一个区间中所有的数字从左到右一次垒起来的次方的幂对m取模之后的数字是多少。

        根据欧拉降幂公式:,这个式子当且仅当x>φ(m)时满足。如此一来,这个次方的过程可以变成一个递归的过程,每一个数字的指数等于后一个数字到右端点的幂。可以预见,这个迭代,相当于也是φ函数的一个迭代,显然当φ函数值等于1的时候已经可以不用往后递归了,而可以证明φ函数嵌套多次,知道数值等于1,它的次数不会超过log(N)。于是总的复杂度就是O(logNlogN),即递归次数和快速幂次数。然后具体实现上,注意式子满足的条件,我们要始终保证返回值如果大于φ,那么对它取模并加上φ,否则不做处理。为了保证不出错,在快速幂的中间阶段取模时就要用这种方式取模,然后在求phi的时候进行记忆化求取,不然会超时。具体见代码:

#include
#define Mod(a,b) a mp;

LL qpow(LL x,LL n,LL mod)
{
    LL res=1;
    while(n)
    {
        if (n&1) res=Mod(res*x,mod),n--;
        x=Mod(x*x,mod); n>>=1;
    }
    return res;
}

LL phi(LL k)
{
    LL i,s=k,x=k;
    if (mp.count(k)) return mp[x];					//记忆化存储
    for(i = 2;i * i <= k; i++)
    {
        if(k % i == 0) s = s / i * (i - 1);
        while(k % i == 0) k /= i;
    }
    if(k > 1) s = s / k * (k - 1);
    mp[x]=s; return s;
}

LL solve(LL l,LL r,LL mod)
{
    if (l==r||mod==1) return Mod(a[l],mod);					//如果到右端点或者φ值等于1,那么直接返回当前数字
    return qpow(a[l],solve(l+1,r,phi(mod)),mod);			//否则指数为[l+1,r]区间的结果
}

int main()
{
    scanf("%lld%lld",&n,&mod);
    for(int i=1;i<=n;i++)
        scanf("%lld",&a[i]);
    scanf("%lld",&q);
    while(q--)
    {
        int L,R;
        scanf("%d%d",&L,&R);
        printf("%lld\n",solve(L,R,mod)%mod);				//对mod取模,因为qpow内部是用Mod(a,b)取模
    }
    return 0;
}

觉得博主写的好的话,打赏一下吧,互利互惠……

                                                                    

 

你可能感兴趣的:(---------Online,Judge--------,CodeForces)