1. 程式人生 > >HDU6395 Sequence 2018多校聯合第七場 代常數矩陣快速冪+分段思維

HDU6395 Sequence 2018多校聯合第七場 代常數矩陣快速冪+分段思維

這道題emmmmmmn...

比賽的時候想到矩陣快速冪了,但分段這個真的是...不好想更不好敲。。後來看了標程,豁然開朗Orz

只能說明。。我好菜啊啊啊啊啊555555...

遞推式如下:(x是不斷更新的量)

                          |  f(n)   |     | D  C  x |    | f(n-1) |

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

                          |    1     |     | 0  0  1 |    | 

   1     |

有個bug就是矩陣相乘的時候順序反了,一般矩陣是不滿足交換律的,所以一定要注意。

附上AC程式碼:

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<ctime>
#include<algorithm>
using namespace std;
#define ll long long
const ll MOD=1e9+7;

ll A,B,C,D,P,n;
struct mat
{
	ll a[3][3];
}c,ans,unit;
mat mul(mat x,mat y,ll n)//注意x,y的順序!!!
{
    mat cnt;
    memset(cnt.a,0,sizeof(cnt.a));
    for(ll i=0;i<n;i++)
        for(ll j=0;j<n;j++)
            for(ll k=0;k<n;k++)
                cnt.a[i][j]=(cnt.a[i][j]+x.a[i][k]*y.a[k][j]%MOD)%MOD;
    return cnt;
}
mat Pow(mat c,ll k)
{
	mat res;
	memcpy(res.a,unit.a,sizeof(res.a));
    while(k>0)
    {
        if(k&1)
            res=mul(res,c,3);
        c=mul(c,c,3);
        k=(k>>1);
    }
    return res;
}
void init(ll x)
{
	c.a[0][0]=D;c.a[0][1]=C;c.a[0][2]=x;
	c.a[1][0]=1;c.a[1][1]=0;c.a[1][2]=0;
	c.a[2][0]=0;c.a[2][1]=0;c.a[2][2]=1;
	return;
}
int main()
{
    memset(unit.a,0,sizeof(unit.a));
	for(int i=0;i<3;i++)
        unit.a[i][i]=1;
    int T;
	scanf("%d",&T);
	while(T--)
	{
		scanf("%lld%lld%lld%lld%lld%lld",&A,&B,&C,&D,&P,&n);
		if(n==1)
            printf("%lld\n",A);
        else if(n==2)
            printf("%lld\n",B);
		else if(n<P)
		{
		    ans=unit;
			for(ll i=3;i<=n;i=P/(P/i)+1)
			{
				init(P/i);
				if(n<=P/(P/i))
                    c=Pow(c,n-i+1);
				else
                    c=Pow(c,P/(P/i)+1-i);
				ans=mul(c,ans,3);
			}
            ll aans=(ans.a[0][0]*B%MOD+ans.a[0][1]*A%MOD+ans.a[0][2]%MOD)%MOD;
            cout<<aans<<endl;
		}
		else if(P<=n)
		{
		    ans=unit;
			for(ll i=3;i<=P;i=P/(P/i)+1)
			{
				init(P/i);
				c=Pow(c,P/(P/i)+1-i);
				ans=mul(c,ans,3);
			}
			init(0);
			c=Pow(c,n-max(P,(ll)2));
			ans=mul(c,ans,3);
            ll aans=(ans.a[0][0]*B%MOD+ans.a[0][1]*A%MOD+ans.a[0][2]%MOD)%MOD;
            cout<<aans<<endl;
		}
	}
	return 0;
}