『HDU 5895』Mathematician QSC

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5895
转载链接:http://blog.csdn.net/viscu/article/details/52595126
知识点链接:http://blog.csdn.net/acdreamers/article/details/8236942

题意:就是求一个公式 这里写图片描述

个人感想:
今天补补我没看过的题,我一拿到题,然后拆分一下,我想,不就矩阵快速幂吗,对于每个 f[i]^2 求一个快速幂,然后我看了一下n*y,这个数据<=10^12次方,就算用nlogn求完指数也会超时,…然后我就想不出来了,我考虑过,能不能用矩阵把g【n】一起求出来,然后想了会实在没头绪,- -之后无奈下看了下转载写的题解,… 我曹,这样构造矩阵也可以…,我服…我做这种类型构造有点少啊…所以也没什么感觉,
然后我就觉得这样很简单啊,xjb搞搞就行了… 可是我突然发现…不行啊 应该可以取模才对啊,否则指数无限大啊。。。
我再查了一下取模公式 只有**(a^b)%p ==((a%p)^p)%p**;
但是没用啊。。。。
再百度一下 指数循环节,题解也提到过,看看ACdreamer写的… 没什么解释,就摆了一条公式, 窝尼玛,真牛,我感觉我得去刷刷矩阵幂和 ACdream给的指数循环了… 那里有好多题目…

真的久不做矩阵,我还犯了个错误,原来矩阵是不能交换律的…(⊙o⊙)哦!!!!!,然后测了很久才发现错误…

分析:矩阵快速幂+循环节.

代码:

/* Author:GavinjouElephant
 * Title:
 * Number:
 * main meanning:
 *
 *
 *
 */


#include <iostream>
using namespace std;
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <sstream>
#include <cctype>
#include <vector>
#include <set>
#include <cstdlib>
#include <map>
#include <queue>
//#include<initializer_list>
//#include <windows.h>
//#include <fstream>
//#include <conio.h>
#define MaxN 0x7fffffff
#define MinN -0x7fffffff
#define lson 2*k
#define rson 2*k+1
typedef long long ll;
const int INF=0x3f3f3f3f;
const int maxn=1e5+10;
int Scan()//读入整数外挂.
{
    int res = 0, ch, flag = 0;

    if((ch = getchar()) == '-')             //判断正负
        flag = 1;

    else if(ch >= '0' && ch <= '9')           //得到完整的数
        res = ch - '0';
    while((ch = getchar()) >= '0' && ch <= '9' )
        res = res * 10 + ch - '0';
    return flag ? -res : res;
}
 void Out(int a)    //输出外挂
 {
     if(a>9)
         Out(a/10);
     putchar(a%10+'0');
 }
 int T;
 ll n,y,x,s;
 typedef vector<ll> vec;
 typedef vector<vec> mat;
 int M;
 mat mul(mat &A,mat &B)
 {
     mat C(A.size(),vec(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;
             }
         }
     }
     return C;
 }

ll pow(mat A,ll n)
 {
     if(n<=1) return n;

     n-=1;
     mat B(A.size(),vec(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;
     }

//     for(int i=0;i<B.size();i++)
//     {
//         for(int j=0;j<B[0].size();j++)
//         {
//             cout<<B[i][j]<<" ";
//         }
//         cout<<endl;
//     }
//     cout<<"--->B"<<endl;

     mat D(4,vec(4));
     D[0][0]=1;
     D[3][0]=1;
//
//     for(int i=0;i<D.size();i++)
//     {
//         for(int j=0;j<D.size();j++)
//         {
//             cout<<D[i][j]<<" ";
//         }
//         cout<<endl;
//     }
//     cout<<endl;

     D=mul(B,D);


//     for(int i=0;i<D.size();i++)
//     {
//         for(int j=0;j<D.size();j++)
//         {
//             cout<<D[i][j]<<" ";
//         }
//         cout<<endl;
//     }
//     cout<<endl;

     return D[3][0]%M;
 }

 ll ouler(ll x)
 {
     ll res=x;
     for(int i=2;i*i<=x;i++)
     {
         if(x%i==0)
         {
             res=res/i*(i-1);
             while(x%i==0) x/=i;
         }
     }
     if(x>1) res=res/x*(x-1);

     return res;
 }
 ll qmod(ll a,ll n,ll mod)
 {
     ll res=1;
     while(n)
     {
        if(n&1)res=(res*a)%mod;
        a=(a*a)%mod;
        n>>=1;
     }
     return res%mod;
 }
 void solve()
 {
     mat A(4,vec(4));
     A[0][0]=4;A[0][1]=4;A[0][2]=1;A[0][3]=0;
     A[1][0]=2;A[1][1]=1;A[1][2]=0;A[1][3]=0;
     A[2][0]=1;A[2][1]=0;A[2][2]=0;A[2][3]=0;
     A[3][0]=4;A[3][1]=4;A[3][2]=1;A[3][3]=1;

     ll zhi=pow(A,n*y)%M+M;


     printf("%I64d\n",qmod(x,zhi,s+1));

 }


int main()
{
#ifndef ONLINE_JUDGE
    freopen("coco.txt","r",stdin);
    freopen("lala.txt","w",stdout);
#endif
    scanf("%d",&T);
    while(T--)
    {
        scanf("%I64d%I64d%I64d%I64d",&n,&y,&x,&s);
        M=ouler(s+1);

        solve();

    }

    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值