天天看點

hdoj 5895 Mathematician QSC 【數論----矩陣快速幂求解類斐波那契數列】

Mathematician QSC

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)

Total Submission(s): 342    Accepted Submission(s): 184

Problem Description

QSC dream of becoming a mathematician, he believes that everything in this world has a mathematical law.

Through unremitting efforts, one day he finally found the QSC sequence, it is a very magical sequence, can be calculated by a series of calculations to predict the results of a course of a semester of a student.

This sequence is such like that, first of all,

f(0)=0,f(1)=1,f(n)=f(n−2)+2∗f(n−1)(n≥2)Then the definition of the QSC sequence is 

g(n)=∑ni=0f(i)2. If we know the birthday of the student is n, the year at the beginning of the semester is y, the course number x and the course total score s, then the forecast mark is 

xg(n∗y)%(s+1).

QSC sequence published caused a sensation, after a number of students to find out the results of the prediction is very accurate, the shortcoming is the complex calculation. As clever as you are, can you write a program to predict the mark?

Input

First line is an integer T(1≤T≤1000).

The next T lines were given n, y, x, s, respectively.

n、x is 8 bits decimal integer, for example, 00001234.

y is 4 bits decimal integer, for example, 1234.

n、x、y are not negetive.

1≤s≤100000000

Output

For each test case the output is only one integer number ans in a line.

Sample Input

2

20160830 2016 12345678 666

20101010 2014 03030303 333

Sample Output

1

317

Source

​​2016 ACM/ICPC Asia Regional Shenyang Online​​

Recommend

wange2014   |   We have carefully selected several similar problems for you:  

​​5901​​​ 

​​​5900​​​ 

​​​5899​​​ 

​​​5898​​​ 

​​​5897​​ 

推出公式:

1.    F(n)=  G(n)*G(n+1)/2:;

2.    F  ( n)= 5* F(n-1) + 5* F(n-2)-F(n-3)

公式:

(x^n)%c=x^(n%phi(c)+phi(c))%c;

原則:

方陣有結合律---沒有交換律

思路:

先求出phi(s+1)--然後用矩陣求出F(n)%phi+phi---

然後快速幂求答案---

構造矩陣

A:

5  5 -1

1  0  0

0  1  0

和列向量

B

F [ 2 ]

F [ 1 ]

F [ 0 ]

C =A*B=

F [ 3 ]

F [ 2 ]

F [ 1 ]

F [ n ]                  F ( n-1 )                                      F [ 2 ]

F [ n-1]   =  A *   F ( n-2 )    =A...........=A^(n-2)*   F [ 1 ]

F [n-2]                F (n-3)

代碼1:

注意:

   F(n)=  G(n)*G(n+1)/2:

  因為最後要除2---是以取模時我們要對2*phi取模-----

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define LLL long long
LLL mod;
struct node{
  LLL shu[2][2];
  void clear()
  {
    for (int i=0;i<2;i++)
      for (int j=0;j<2;j++)
        shu[i][j]=0;
  }
  node operator * (const node &B) const
  {
    node C;
    C.clear();
    for (int i=0;i<2;i++)
      for (int j=0;j<2;j++)
        for (int k=0;k<2;k++)
          C.shu[i][j]=(C.shu[i][j]+shu[i][k]*B.shu[k][j])%mod;
        return C;
  }
}A,B,C,D;
LLL P[2]={0,1};
LLL phi(LLL xx)
{
  LLL lp=xx;
  for (LLL i=2;i*i<=xx;i++)
  {
    if (xx%i==0)
    {
      lp=lp-lp/i;
      while (xx%i==0)
      xx/=i;
    }
  }
  if (xx>1)
  lp=lp-lp/xx;
  return lp;
}
LLL g(LLL xx)
{
  LLL lp;
  mod*=2;//注意
  A.clear();
  for (int i=0;i<2;i++)
  A.shu[i][i]=1;
  B.clear();
  B.shu[1][0]=B.shu[0][1]=1;
  B.shu[0][0]=2;
  if (xx<3)
  return P[xx];
  while (xx)
  {
    if (xx&1)
    A=A*B;
    B=B*B;
    xx>>=1;
  }
  lp=0;
  lp=(A.shu[0][0]*A.shu[0][1])/2;
  mod/=2;//注意
  lp+=mod;
  return lp;
}
void slove(LLL x,LLL n,LLL s)
{
  mod=phi(s);
  LLL lp=g(n);
  LLL ans=1;
  while (lp)
  {
    if (lp&1)
    ans=(ans*x)%s;
    x=(x*x)%s;
    lp>>=1;
  }
  printf("%lld\n",ans);
}
int main()
{
  int t;scanf("%d",&t);
  while (t--)
  {
    LLL n,y,x,s;
    scanf("%lld%lld%lld%lld",&n,&y,&x,&s);
    n*=y;
    s+=1;
    slove(x,n,s);
  }
  return 0;
}      
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define LLL long long
LLL mod;
struct node{
  LLL shu[3][3];
  void clear()
  {
    for (int i=0;i<3;i++)
      for (int j=0;j<3;j++)
        shu[i][j]=0;
  }
  node operator * (const node &B) const
  {
    node C;
    C.clear();
    for (int i=0;i<3;i++)
      for (int j=0;j<3;j++)
        for (int k=0;k<3;k++)
          C.shu[i][j]=(C.shu[i][j]+shu[i][k]*B.shu[k][j])%mod;
        return C;
  }
}A,B,C,D;
LLL P[3]={0,1,5};
LLL phi(LLL xx)
{
  LLL lp=xx;
  for (LLL i=2;i*i<=xx;i++)
  {
    if (xx%i==0)
    {
      lp=lp-lp/i;
      while (xx%i==0)
      xx/=i;
    }
  }
  if (xx>1)
  lp=lp-lp/xx;
  return lp;
}
LLL g(LLL xx)
{
  LLL lp;
  A.clear();
  for (int i=0;i<3;i++)
  A.shu[i][i]=1;
  B.clear();
  B.shu[0][0]=B.shu[0][1]=5;B.shu[0][2]=-1;
  B.shu[1][0]=B.shu[2][1]=1;
  if (xx<3)
  return P[xx];
  xx-=2;
  while (xx)
  {
    if (xx&1)
    A=A*B;
    B=B*B;
    xx>>=1;
  }
  lp=0;
  for (int i=0;i<3;i++)
  lp=(lp+A.shu[0][i]*P[2-i])%mod;
  lp+=mod;
  return lp;
}
void slove(LLL x,LLL n,LLL s)
{
  mod=phi(s);
  LLL lp=g(n);
  LLL ans=1;
  //printf("%lld   %lld   %lld    %lld\n",x,lp,s,mod);
  while (lp)
  {
    if (lp&1)
    ans=(ans*x)%s;
    x=(x*x)%s;
    lp>>=1;
  }
  printf("%lld\n",ans);
}
int main()
{
  int t;scanf("%d",&t);
  while (t--)
  {
    LLL n,y,x,s;
    scanf("%lld%lld%lld%lld",&n,&y,&x,&s);
    n*=y;
    s+=1;
  //  printf("%lld %lld %lld\n",x,n,s);
    slove(x,n,s);
  }
  return 0;
}