HDU 5171 GTY's birthday gift

来源:互联网 发布:迈普数据王锐睿 编辑:程序博客网 时间:2024/05/14 12:48
#include <cstdio>#include <cstring>#include <cmath>#include <iostream>#include <algorithm>using namespace std;#define LL long longstruct 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项和即可,转移矩阵如下:
                                             
0 0
原创粉丝点击