HDU 5171 GTY's birthday gift

本文介绍了一种使用矩阵快速幂的方法来高效解决类似斐波那契数列的问题,特别关注如何通过矩阵运算求解特定类型的数列前n项和。文章提供了一个具体的C++实现示例。
#include <cstdio>
#include <cstring>
#include <cmath>
#include <iostream>
#include <algorithm>

using namespace std;

#define LL long long

struct Mat{
    LL f[3][3];
};

LL MOD = 10000007;

int a[100010];

Mat mul(Mat a,Mat b)
{
    LL i,j,k;
    Mat c;
    memset(c.f,0,sizeof(c.f));
    for(i=0;i<3;i++)
        for(j=0;j<3;j++)
        {
        	if(a.f[i][j]==0)
        		continue;
            for(k=0;k<3;k++)
            {
            	if(b.f[j][k]==0)
					continue;
				c.f[i][k]= (c.f[i][k]+a.f[i][j]*b.f[j][k])%MOD;
			}
        }
    return c;
}

Mat pow_mod(Mat e,LL b)
{
    Mat s;
    memset(s.f,0,sizeof(s.f)) ;
	for(int i=0;i<3;i++)
		s.f[i][i]=1;
	while(b)
    {
        if(b&1)
            s=mul(s,e);
        e=mul(e,e);
        b=b>>1;
    }
    return s;
}

int main()
{
    int n,k;
    while(~scanf("%d%d",&n,&k))
	{
        LL sum=0;
        for(int i=0;i<n;i++)
        {
        	scanf("%d",&a[i]);
        	sum+=a[i];
		}
		sort(a,a+n);
        Mat e;
        e.f[0][0]=1;e.f[0][1]=1;e.f[0][2]=1;
        e.f[1][0]=0;e.f[1][1]=1;e.f[1][2]=1;
        e.f[2][0]=0;e.f[2][1]=1;e.f[2][2]=0;
        e=pow_mod(e,k);
        LL ans=((e.f[0][0]*sum+e.f[0][1]*a[n-1]+e.f[0][2]*a[n-2])%MOD+MOD)%MOD;   //可能负数结果 
        //printf("%lld\n",ans);
        printf("%I64d\n",ans);
    }
    return 0;
}

显然每次会从可重集中选择最大的两个进行操作,设这两数为a,b(a>=b),操作之后的数一定是操作后集合中最大的,下一次选取的数一定是a+ba,这就形成了一个类似于斐波那契数列的东西,矩阵乘法快速幂求前n项和即可,转移矩阵如下:



                
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值