牛客 復讀陣列(矩陣加速 數學)

2022-03-17 03:44:26 字數 2274 閱讀 7201

有乙個長為n×k的陣列,它是由長為n的陣列a1,a2,…,an重複k次得到的。

定義這個陣列的乙個區間的權值為它裡面不同的數的個數,現在,你需要求出對於這個陣列的每個非空區間的權值之和。

答案對109+7取模。

第一行兩個整數n和k。

接下來一行n個整數,第i個整數為ai。

輸出乙個整數,表示答案。

示例1輸入

2 21 2

輸出16

說明陣列為1, 2, 1, 2。

對於長為1的區間,共4個,權值為1。

對於長度》1的區間,可以發現權值均為2,共6個。

那麼權值和為1×4+2×6=16。

備註:對於前10%的資料n≤5。

對於前20%的資料n≤100。

對於前40%的資料n≤1000。

對於另外10%的資料n≤100,k=1。

對於另外10%的資料n≤1000,k=1。

對於另外10%的資料n≤105,k=1。

對於所有資料,1≤n≤105,1≤k≤109,1≤ai≤109。

分析反正我沒打正解

如果k=1,那麼我們可以轉換角度考慮每種顏色的貢獻。

對於每段區間,包含這個顏色則這個顏色對該區間的貢獻為1,不包含這個顏色則這個顏色對該區間的貢獻為0

所以就是要求取有多少段區間包含這個顏色,那麼我們可以存下這個顏色在原陣列的分布位置然後進一步討論

假設分布的情況如下,白色代表其他顏色

現在考慮如何計數。我們可以固定區間的右端點,然後尋找包含這個顏色的左端點,比如

比如當右端點在[3,6]時,左端點的範圍都是[1,3],當右端點的範圍在[7,9]時,左端點的範圍都是[1,7]。

這樣我們就這可以找出規律然後計算了(講道理可以用總的合法的減去不合法的,但我沒試過也不知道對不對

此時對於k=1時我們就可以解出來答案。

但是看到k≤109

,把相同的陣列拼接起來,貌似分類討論挺麻煩的

可以試試遞推

設f[k]表示k個陣列拼起來的答案

對於新加入的陣列,如果不看最右邊的那乙個,增加的貢獻應該就是由k-2個陣列拼成k-1個陣列增加的貢獻,即f[k-1]-f[k-2]

現在考慮最右邊的陣列,那麼還沒計算貢獻的區間就是左端點在新加入的陣列內,右端點在最右邊陣列內的區間

當k>=3時,顯然這些區間都跨越了乙個陣列,貢獻都是顏色總數,所以總的貢獻為n*n*c(c為顏色總數)

所以得出遞推是,f[k]=f[k-1]+f[k-1]-f[k-2]+n*n*c(k>=3),這東西可以矩陣加速。

對於f[1],f[2],我們可以暴力求

然後,就沒有然後了

code

#include#include

#include

#include

#include

using

namespace

std;

const

int mod=1e9+7

;const

int maxn=100005

;int n,k,id,a[maxn<<1],f[5

];struct nodex,y;

mapmp;vectorg[maxn];

node

operator *(node a,node b)

intmain()

for(int i=1;i<=id;g[i].clear(),i++)

for(int i=1;i<=2*n;i++)g[mp[a[i]]].push_back(i);

for(int i=1;i<=id;g[i].clear(),i++)

x.mat[

1][1]=f[1];x.mat[1][2]=f[2];x.mat[1][3]=1ll*n*n*id%mod;

y.mat[

1][2]=-1;y.mat[2][1]=1;y.mat[2][2]=2;y.mat[3][2]=1;y.mat[3][3]=1

; k--;while(k)

printf(

"%d\n

",x.mat[1][1

]);}

牛客 復讀陣列

將乙個長度為n nn的陣列複製成k kk份,然後每個區間的值是乙個區間中不同的數的數量,求每個非空區間的值和。若乙個區間長度 n n n那麼他們的值是固定的,所以我們可以先計算出這些區間的答案。現在只需要考慮長度 n n的區間,我們講原陣列複製乙份放到後面後,我們用f if i fi 表示第i ii...

牛客網 把陣列排成最小的數

題目描述 輸入乙個正整數陣列,把陣列裡所有數字拼接起來排成乙個數,列印能拼接出的所有數字中最小的乙個。例如輸入陣列,則列印出這三個數字能排成的最小數字為321323。coding utf 8 利用 sorted 設定比較方法lambda class solution def printminnumb...

牛客網 把陣列排成最小的數

輸入乙個正整數陣列,把陣列裡所有數字拼接起來排成乙個數,列印能拼接出的所有數字中最小的乙個。例如輸入陣列,則列印出這三個數字能排成的最小數字為321323。import j a.util.arraylist import j a.util.collections import j a.util.co...