1. 程式人生 > >HDU 6395 矩陣快速冪

HDU 6395 矩陣快速冪

矩陣很好構造:

F:  f(n)                      A:   D           C            1                       B:   f(n-1)

     f(n-1)                         1            0             0                             f(n-2)

     CC(常數)                   0            0             CC                          1

CC是在變化的,但有的一段區間內是保持不變的;

比如:10/6,10/7,10/8,10/9,10/10 它們的都是1

對於不變的可以用矩陣加速,我們知道最後一個相等的下標為:p/(p/i)

還要注意一些細節

程式碼:

#include <set>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <string> 
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <functional> 
#define PI acos(-1)
typedef long long ll;
using namespace std;
const ll INF = 0xffffffff;
const ll mod=1e9+7;
ll a,b,c,d,p,n; 
struct node
{
    ll num[3][3];
}A;
void init()
{
   for(ll i=0;i<3;i++)
       for(ll j=0;j<3;j++)
           A.num[i][j]=0;
   A.num[0][0]=d;A.num[0][1]=c;
   A.num[1][0]=1;A.num[2][2]=1;
}
node mul(node AA,node BB)
{
    node C;
    for(ll i=0;i<3;i++)
    {
        for(ll j=0;j<3;j++)
        {
            C.num[i][j]=0;
            for(ll k=0;k<3;k++)
            {
               C.num[i][j]+=AA.num[i][k]*BB.num[k][j];
               C.num[i][j]%=mod;
			}
		}
	}
	return C;
}
node Pow(ll nn,ll T,node B)
{
   init();
   A.num[0][2]=T;
   while(nn>0)
   {
      if(nn&1)B=mul(A,B);
      A=mul(A,A);
      nn=nn>>1;
   }
   return B;
}
void solve()
{
   ll x,i,last,nn;
   node B;
   B.num[0][0]=b;
   B.num[1][0]=a;
   B.num[2][0]=1;
   for(i=3;i<=n;i=last+1)
   {
      x=p/i;
      if(x==0)break;
	  last=p/(p/i);
	  nn=last-i+1;
	  if(last>n)nn=n-i+1;
	  B=Pow(nn,x,B);
   }
   nn=n-i+1;
   if(i<=n)B=Pow(nn,0,B);
   cout<<B.num[0][0]<<endl;
}
int main()
{
    ll t;
    cin>>t;
	while(t--)
    {
        cin>>a>>b>>c>>d>>p>>n;
        if(n==1){cout<<a<<endl;continue;}
        if(n==2){cout<<b<<endl;continue;}
		solve();
	}
}