BZOJ4547 小奇的集合(矩乘)

2021-07-16 20:02:25 字數 1934 閱讀 4764

傳送門

由於資料保證最後的答案為非負數,那麼序列就有兩種情況:

1、序列中有兩個或兩個以上非負數。

2、序列中只有乙個非負數。

對於第一種情況,每一次的操作一定是將最大的兩個數相加放入序列中。比如有不降序列:a1

,a2,

a3……

,an−

1,an

,進行多次操作就可以寫出如下的序列: a1

,a2,

a3…a

n−1,

an,a

n−1+

an a

1,a2

,a3…

an−1

,an,

an−1

+an,

an−1

+2an

a1,a2,a

3…an

−1,a

n,an

−1+a

n,an

−1+2

an,2

an−1

+3an

a1,a2,a

3…an

−1,a

n,an

−1+a

n,an

−1+2

an,2

an−1

+3an

,3an

−1+5

an .

..可以看出an

−1和a

n 的係數呈斐波那契數列。那麼我們就需要求斐波那契數列的字首和,這個o(

k)的遞推可以用矩陣快速冪來加速。 [s

n−1f

nfn−

1]∗⎡

⎣⎢11

0011

010⎤

⎦⎥=[

snfn

+1fn

] 對於第二種情況,一定是唯一的乙個非負數數和數列中的最大的負數相加,直到數列中有兩個非負數,再進行第一種操作。

我的方法比較麻煩,用等差數列的求和公式求出負數和非負數相加過程中的和。實際上由於|a

i|<=

100000

,可以直接暴力計算。

#include

#include

#include

#include

using namespace std;

#define ll long long

#define n 100005

#define mod 10000007

int n,p;

struct hpa,unit,mi,ans;

ll a[n],sum,s1,s2,k1,k2;

inline hp cheng(hp a,hp b)

inline hp fast_pow(hp a,int p)

int main()

else

if (p==0)

for (int i=1;i<=3;++i)

for (int j=1;j<=3;++j) unit.a[i][j]=ans.a[i][j]=0;

for (int i=1;i<=3;++i) unit.a[i][i]=1;

a.a[1][1]=a.a[2][1]=a.a[2][2]=a.a[2][3]=a.a[3][2]=1;

mi=fast_pow(a,p-1);

ans.a[1][1]=ans.a[1][2]=ans.a[1][3]=1;

ans=cheng(ans,mi);

k1=ans.a[1][1]; k2=(ans.a[1][1]-1+ans.a[1][2])%mod;

sum=(sum+(s1*k1

%mod+s2*k2

%mod)%mod)%mod;

sum=((sum%mod)+mod)%mod;

printf("%lld\n",sum);

}

1、考慮問題情況要全面。

BZOJ4547 小奇的集合

有乙個大小為n的可重集s,小奇每次操作可以加入乙個數a b a,b均屬於s 求k次操作後它可獲得的s的和的最大值。資料保證這個值為非負數 很顯然,我們每次肯定是取集合中最大的兩個數,那麼我們設這兩個數為 a b,當前的和為 s 顯然有轉移 a b,b a b,s a b s,那麼用矩陣乘法加速即可。...

BZOJ4547 Hdu5171 小奇的集合

給有乙個大小為n的可重集s,每次操作可以加入乙個數a b a,b均屬於s 求k次操作後它可獲得的s的和的最大 值。資料保證這個值為非負數 我們先來看看,因為我們要得到最大的s,所以每次我們都要使得a b最大 首先排除一開始得到的a,b為負數的情況,我們將a b放進s裡,那麼下一次操作就會將a a b...

BZOJ 4548 小奇的糖果

有 n 個彩色糖果在平面上。小奇想在平面上取一條水平的線段,並拾起它上方或下方的所有糖果。求出最多能夠拾 起多少糖果,使得獲得的糖果並不包含所有的顏色。包含多組測試資料,第一行輸入乙個正整數 t 表示測試資料組數。接下來 t 組測試資料,對於每組測試資料,第一行輸入兩個正整數 n k,分別表示點數和...