Snail Alice HDU

来源:互联网 发布:柏曼灯具 知乎 编辑:程序博客网 时间:2024/04/27 01:22


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 longusing 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  点击打开链接






原创粉丝点击