Snail Alice HDU - 3411


Snail Alice  HDU - 3411 


A function f(n), n is a positive integer, and


Given q and n, please calculate the value of f(n).Please note that q and n could be huge.

Input

Input consists of multiple test cases, and ends with a line of “-1 -1 -1”.
For each test case:
The first line contains three integers x1, y1 and z1, representing q. q=x1^y1+z1.
The second line contains two integers: y2 and z2, representing n. n=2^y2+z2.
The third line contains a single integer P, meaning that what you really should output is the formula’s value mod P.
Note: 0<=x1,y1,z1,y2,z2<=50000, z1>0, 0<P<100000000

Output

For each test case, print one line containing an integer which equals to the formula’s value mod P.

Sample Input

2 1 3
0 0
32551
3 0 5
0 2
70546
-1 -1 -1

Sample Output

31


題目太長,所以縮減了一下,題意就是求  上面的那個式子。


思路:  看數據範圍,直接求肯定不可能,那麼先假定 q 爲一個比較小的數,然後 以  n打表,找出遞推式,

就有  f(n )=(q-1)f(n-1)+qf(n-2);然後求遞推式就是矩陣快速冪了,

  

 但是  n 非常大  (n=2^y2+z2) ,又

 據矩陣快速冪,對於指數的二進制是1 的,需要將底數跟答案相乘,如果爲0 的,則不需要。

 那麼直接考慮  n-1  ,(2^y2-1) +z2  ,

 可以分兩步計算,先算出 q^z2,直接快速冪,再算前面的,(2^y2-1)  的二進制全部爲1 ,根據上面的性質直接求 解。

 

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<string>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<queue>
#include<stack>
#include<vector>
#include<algorithm>
#define maxn 10010
#define INF 0x3f3f3f3f
#define eps 1e-8
#define MOD 1000000007
#define ll long long
using namespace std;

int x1,y11,z1;
int y2,z2;
ll p;
ll Pow(int a,int b,ll mod)
{
    ll ans=1;
    ll aa=a;
    while(b)
    {
        if(b&1) ans=(ans*aa)%mod;
        aa=aa*aa%mod;
        b>>=1;
    }
    return ans%mod;
}
struct Node{

    ll a[3][3];
    void clear()
    {
        memset(a,0,sizeof a);
    }
    friend  Node operator *(Node aa,Node bb);

};
Node operator *(Node aa,Node bb)
{
    Node ans;
    for(int i=0;i<2;i++)
    {
        for(int j=0;j<2;j++)
        {
            ans.a[i][j]=0;
            for(int k=0;k<2;k++)
            {
                ans.a[i][j]+=aa.a[i][k]*bb.a[k][j];
            }
            ans.a[i][j]%=p;
        }
    }
    return ans;
}
int main()
{
    while(scanf("%d%d%d",&x1,&y11,&z1)!=EOF)
    {
        if(x1==-1&&y11==-1&&z1==-1)
            break;
        scanf("%d%d",&y2,&z2);
        scanf("%lld",&p);
        ll q=(ll)(Pow(x1,y11,p)+z1)%p;
        Node s,b,m;
        s.clear(); m.clear();b.clear();
        s.a[0][0]=(q-1+p)%p;
        s.a[0][1]=q;
        s.a[1][0]=1;
        s.a[1][1]=0;
        b.a[0][0]=1;
        b.a[1][0]=0;
        m=s;
        while(z2)
        {
            if(z2&1)
                b=m*b;
            z2>>=1;
            m=m*m;
        }
        for(int i=0;i<y2;i++)
        {
            b=s*b;
            s=s*s;
        }
        printf("%lld\n",b.a[0][0]);
    }
    return 0;
}





對於上面 的那個快速冪的性質的解釋:

其實在寫 快速冪的時候就已經運用了:

{...  if(b&1) ...}

詳細解釋: 

進行快速冪時可以發現,進行的是移位運算,對於指數某一位是1的,就讓答案和底數相乘一次,因此模擬y2位的矩陣快速冪,然後再進行z2次快速冪即可。例如2^10, 10的二進制表示 1010 

n=2,m=10,b=1;

1、(1&0==0)  m=m>>1=101,n=n*n=4
2、(1&1==1)   b=b*n=4,m=m>>1=10,n=n*n=16 
3、(0&1==0)  m=m>>1=1,n=n*n=16*16  
4、(1&1==1)  b=b*n=4*16*16 m=m>>1=0 n=n*n; break;

  from  點擊打開鏈接






發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章