《洛谷P5343 XR 1 分塊》

2022-06-19 20:03:10 字數 3267 閱讀 7514

一道非常好的題,太菜了調了很久,細節非常多。

首先,將題意轉化一下,由給定的兩段都有的長度,可以組成多少種組合。

設dp[i]表示,長度為i的方案數。

那麼有轉移,$dp[i] = \sum_^ dp[i-a[j]]$//tot為兩段都有的元素個數,注意要去重

這裡雖然可以用無限數量的揹包思想,但是顯然這樣更好。

然後dp轉移,60分。

//

author: levil

#includeusing

namespace

std;

typedef

long

long

ll;typedef pair

pii;

const

int n = 1e6+5

;const

int m = 2e5+5

;const ll mod = 1e9+7

;#define rg register

#define pi acos(-1)

#define inf 1e9

#define ct0 cin.tie(0),cout.tie(0)

#define io ios::sync_with_stdio(false)

#define dbg(ax) cout << "now this num is " << ax << endl;

namespace

fastio

while(c >= '

0' && c <= '9')

return x*f;

}void print(int

x)

if(x > 9) print(x/10

); putchar(x%10+'0'

); }

}using

namespace

fastio;

void fre()

int vis[105],a[105],tot = 0

;ll dp[n];

//i拆分的方案數

intmain()

int nf;nf =read();

for(rg int i = 1;i <= nf;++i)

sort(a+1,a+tot+1

);

int len = unique(a+1,a+tot+1)-a-1

; tot =len;

dp[0] = 1

;

for(rg int i = 1;i <= n;++i)

printf(

"%lld\n

",dp[n]);

//system("pause");

}

view code

顯然當n過大時,會超時。而且dp也存不下。

可以發現,塊的大小最多為100,也就是代表一開始最多dp[100]。

那麼我們可以矩陣快速冪加速。

構造初始矩陣f[0] ~ f[99]。那麼右端矩陣即為f[1] ~ f[100]。

那麼可以發現,除了第一行,其他行的轉移矩陣就是1的對角線。即[i][i-1]的位置。

對於第一行 由$f[100] = \sum_^ f[100-a[j]]$

我們可知,對於100-a[j]位置都應該是1,但是由於這裡的橫列相乘後,位置其實是相反的,那麼對於100-a[j]的位置,就變成了a[j]位置,那麼我們對所有a[j]位置都變1即可。

然後矩陣快速冪。應該是n-99次,因為左邊到f[99]。

然後矩陣我們處理出了轉移矩陣的k次,假定為res.

現在初始矩陣為ans.那麼 ans * res 和 res * ans是不一樣的。

這就和我們矩陣乘法的位置有關。//就是這裡調了非常久。

所以最後應該是轉移矩陣 * ans。然後答案就是ans[1][1]。

//

author: levil

#includeusing

namespace

std;

typedef

long

long

ll;typedef pair

pii;

const

int n = 1e6+5

;const

int m = 2e5+5

;const ll mod = 1e9+7

;#define rg register

#define pi acos(-1)

#define inf 1e9

#define ct0 cin.tie(0),cout.tie(0)

#define io ios::sync_with_stdio(false)

#define dbg(ax) cout << "now this num is " << ax << endl;

namespace

fastio

while(c >= '

0' && c <= '9')

return x*f;

}void print(int

x)

if(x > 9) print(x/10

); putchar(x%10+'0'

); }

}using

namespace

fastio;

void fre()

int a[105],b[105

];struct

mat};

ll f[

105];

mat quick_mi(mat a,ll b)

return

res;

}int

main()

int nf;nf =read();

while(nf--)

mat ans;memset(ans.m,

0,sizeof

(ans.m));

for(rg int i = 1;i <= 100;++i)

for(rg int i = 2;i <= 100;++i) ans.m[i][i-1] = 1

; f[

0] = 1

;

for(rg int i = 1;i < 100;++i)

if(n < 100) printf("

%lld\n

",f[n]);

else

system(

"pause

");

}

view code

洛谷2801 分塊

題目鏈結 題目描述 教主最近學會了一種神奇的魔法,能夠使人長高。於是他準備演示給xmyz資訊組每個英雄看。於是n個英雄們又一次聚集在了一起,這次他們排成了一列,被編號為1 2 n。每個人的身高一開始都是不超過1000的正整數。教主的魔法每次可以把閉區間 l,r 1 l r n 內的英雄的身高全部加上...

洛谷P1471 分塊 方差

傳送門biu 題目大意 給你乙個序列,對其進行區間修改或區間查詢平均數和方差。這他媽是線段樹啊 可是我就是要用分塊艹過你咬我啊 include using namespace std define db double define n 100005 int n,m,bl n t db a n sum...

蒲公英(洛谷4168分塊)

傳送門 若題目是詢問區間是否有過半眾數,就是主席樹,按值域建樹,不斷判斷左右子樹子節點數量大於 r l 1 2,如果一直可以到葉子節點,則return true,否則return false 若題目是詢問區間是否有過半眾數且帶修改,就是樹套樹 雖然我還沒打過樹套樹 那我們可以考慮分塊做法,n 400...