您的位置:首页 > 其它

hdu 5171 GTY's birthday gift

2016-04-12 11:11 246 查看

GTY's birthday gift

问题描述
GTY的朋友ZZF的生日要来了,GTY问他的基友送什么礼物比较好,他的一个基友说送一个可重集吧!于是GTY找到了一个可重集S,GTY能使用神犇魔法k次,每次可以向可重集中加入一个数 a+b (a,b\in S)a+b(a,b∈S),现在GTY想最大化可重集的和,这个工作就交给你了。
注:可重集是指可以包含多个相同元素的集合

输入描述
多组数据(约3组),每组数据的第一行有两个数n,k(2 \leq n \leq 100000,1 \leq k \leq 1000000000)n,k(2≤n≤100000,1≤k≤1000000000) 表示初始元素数量和可使用的魔法数,第二行包含n个数a(1 \leq a_i \leq 100000)a(1≤a​i​​≤100000)表示初始时可重集的元素

输出描述
对于每组数据,模10000007输出可重集可能的最大和。

输入样例
3 2
3 6 2

输出样例
35


这道题的解题思路很简单,用矩阵快速幂实现一个斐波那契数列求和(初值改变)
难点在于矩阵的构造,首先列出三个要维护的值
| sum |
| a[n-1] |
| a[n-2] |
那么可以想到这个矩阵的下一个形式必然为
| sum+a[n-1]+a[n-2] |
| a[n-1]+a[n-2] |
| a[n-1] |
由此可以得到需要构造的友矩阵为
| 1 1 1 |
| 0 1 1 |
| 0 1 0 |
有了这个友矩阵,就可以进行矩阵快速幂了,先求
| 1 1 1 |
| 0 1 1 | 的K次方,然后再乘以初始矩阵就可以得到sum
| 0 1 0 |

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
using namespace std;
typedef long long LL;
const int maxn=111;
const int Max=1e5+10;
const int MOD=10000007;
int a[Max];
struct matrix
{
int w;
LL m[maxn][maxn];        //注意矩阵也要用LL,不然会出现溢出
matrix(int ww):w(ww){memset(m,0,sizeof(m));};
matrix(){}
};
matrix operator * (matrix a,matrix b)
{
matrix res(3);
LL x;
for(int i=0;i<res.w;i++)
{
for(int j=0;j<res.w;j++)
{
x=0;
for(int k=0;k<res.w;k++)
{
x=(x+(LL)a.m[i][k]*b.m[k][j])%MOD;
}
res.m[i][j]=x;
}
}
return res;
}
matrix fast_cover(int k)
{
matrix base(3);
base.m[0][0]=base.m[0][1]=base.m[0][2]=1;
base.m[1][1]=base.m[1][2]=base.m[2][1]=1;
base.m[1][0]=base.m[2][0]=base.m[2][2]=0;
matrix s(3);
s.m[0][0]=s.m[1][1]=s.m[2][2]=1;
while(k)
{
if(k&1) s=s*base;
base=base*base;
k>>=1;
}
return s;
}
int main()
{
int n,k;LL sum;
while(scanf("%d%d",&n,&k)!=EOF)
{
sum=0;
for(int i=0;i<n;i++)  scanf("%d",&a[i]),sum+=a[i];
sort(a,a+n);
matrix ss=fast_cover(k);
LL ans=(ss.m[0][0]*sum+ss.m[0][1]*a[n-1]+ss.m[0][2]*a[n-2])%MOD;
printf("%I64d\n",ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: