HDU 5895 欧拉定理+快速幂+公式

http://acm.hdu.edu.cn/showproblem.php?pid=5895 

 

题意: F[ x ]=F[ x-1 ] * 2 + F[ x-2 ]   G[ x ]=∑F[ i ]  

   

 问 x^G[ n*Y ] % (s+1)

 

思路:之前BC有过类似的题目,这个题目看完了很后悔。。本来是应该可以A掉的。。

    思路就是利用欧拉定理来让G变小先。。然后快速幂搞一下。。。

    类似斐波那契数列一样。。打表试一试就发现 G[ N ] = F[n]*F[n+1]/2  (证明和斐波那契那个证明方法差不多,两遍同时×F[ n-1 ]),移项累加就好。

    所以就很愉快了,但是注意!!!

    这里明显除以2是要求一下逆元的!但是逆元显然不一定存在,所以利用求任意逆元的方法,a/b  mod c = a  mod(b*c)/b

    ( 最后时间紧张加上基础不牢靠并没有想起来。。十分遗憾 。。。)

 

代码:

 

#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <cstring>
#include <vector>
using namespace std;

typedef vector<vector<long long> > mat;

long long M ;
long long M2 ;

mat mul(const mat &A,const mat &B){
    mat C(A.size(),vector<long long>(B[0].size()));
    for(int i = 0; i < A.size(); i++)
        for(int k = 0; k < B.size(); k++)
            for(int j = 0; j < B[0].size(); j++){
                C[i][j] = (C[i][j] + (A[i][k] * B[k][j])%M) % M;
            }
    return C;
}

mat pow(mat A, long long n){
    mat B(A.size(), vector<long long>(A.size()));
    for(int i = 0; i < A.size(); i++){
        B[i][i] = 1;
    }
    while(n>0){
        if(n & 1) B =mul(B,A);
        A = mul(A,A);
        n >>= 1;
    }
    return B;
}

long long Qpow(long long a,long long n){
    long long ans = 1;
    while(n){
        if(n&1) ans = (ans*a)%M2;
        a = (a*a)%M2;
        n >>= 1;
    }
    return ans;
}

long long E(long long n) {
    long long ans = n;
    for (int i = 2; i * i <= n; ++i) {
        if (n % i == 0) {
            ans -= ans / i;
            while (n % i == 0) {
                n /= i;
            }
        }
    }
    if (n > 1) {
        ans -= ans / n;
    }
    return ans;
}

int main(){
    int t;
    scanf("%d",&t);
    vector<long long> v1,v2,v3,v4;
    v1.push_back(2);v1.push_back(1);
    v2.push_back(1);v2.push_back(0);
    v3.push_back(1);
    v4.push_back(0);
    mat A,B;
    A.push_back(v1);A.push_back(v2);
    B.push_back(v3);B.push_back(v4);
    while(t--){
        int n,y,x,s;
        scanf("%d%d%d%d",&n,&y,&x,&s);
        long long Mi=(long long)n*y;
        if(Mi<=11){
            long long a=0,b=1;
            long long sum=0;
            for(int i=1;i<=Mi;i++){
                long long c=b;
                b=c*2+a;
                a=c;
                sum+=a*a;
            }
            M2=s+1;
            cout<<Qpow(x,sum)%M2<<endl;
        }
        else{
            M=E(s+1)*2;
            mat C=pow(A,Mi);
            mat D=mul(C,B);
            long long Fin=(D[0][0]*D[1][0])%M/2+M/2;
            M2=s+1;
            cout<<Qpow(x,Fin)%M2<<endl;
        }
    }
}



 

posted @ 2016-09-21 14:03  zhangxianlong  阅读(178)  评论(1编辑  收藏  举报