zoukankan      html  css  js  c++  java
  • 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;
            }
        }
    }



  • 相关阅读:
    csuoj 1111: 三家人
    csu oj 1339: 最后一滴血
    csuoj 1337: 搞笑版费马大定理
    csuoj 1334: 好老师
    csu oj 1330 字符识别?
    C++动态内存分配
    变量内存分配
    codevs 2235 机票打折
    contesthunter CH Round #64
    面试分享:一年经验初探阿里巴巴前端社招
  • 原文地址:https://www.cnblogs.com/zhangxianlong/p/10672543.html
Copyright © 2011-2022 走看看