bzoj 4547: Hdu5171 小奇的集合

来源:互联网 发布:自适应阈值分割算法 编辑:程序博客网 时间:2024/04/27 14:22
读题,发现就是每次找两个最大的数,加入a+b,矩乘优化一下就好。
然而,wa*inf,原因如下:
1.读错题,答案求的是集合内所有数的和,我写成了所有加入的数的和
2.忘记负数取模的问题
3.不一定,A<B<A+B,比如-3,1,-2,但是由于a[i]比较小,暴力跑出来这部分就行。
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
 
#define ll long long
#define inf 1e9
#define eps 1e-8
#define md 10000007
using namespace std;
struct Ju
{
ll a[3][3];
int x,y;
ll *operator [] (int x) { return a[x];}
} a,ju,mid,ans;
 
Ju operator *=(Ju &a,Ju &b)
{
memset(mid.a,0,sizeof(mid.a)); mid.x=a.x; mid.y=b.y;
for (int i=0;i<a.x;i++)
for (int j=0;j<b.y;j++)
for (int k=0;k<a.y;k++)
mid[i][j]=(mid[i][j]+a[i][k]*b[k][j])%md;
a=mid;
}
 
void kpow(Ju &a,int b)
{
memset(ans.a,0,sizeof(ans.a)); ans.x=a.x; ans.y=a.y;
for (int i=0;i<a.x;i++) ans[i][i]=1;
while (b)
{
if (b&1) ans*=a;
a*=a; b>>=1;
}
a=ans;
}
int main()
{
int n,k;
scanf("%d%d",&n,&k);
int A=-inf,B=-inf,sum=0;
for (int i=1;i<=n;i++)
{
int x;
scanf("%d",&x);
sum=(sum+x)%md;
if (x>A) { B=A; A=x;}
else if (x>B) { B=x;}
}
while (B<=0) { k--; B+=A; sum=(sum+B)%md;}
ju[0][0]=0; ju[0][1]=1; ju[0][2]=1;
ju[1][0]=1; ju[1][1]=1; ju[1][2]=1;
ju[2][0]=0; ju[2][1]=0; ju[2][2]=1;
ju.x=ju.y=3;
kpow(ju,k);
a.x=1; a.y=3; a[0][0]=B; a[0][1]=A; a[0][2]=0;
a*=ju; printf("%lld\n",(a[0][2]+sum+md)%md);
return 0;
}

0 0
原创粉丝点击