SXOI2016 部分解題報告

2022-05-29 06:12:13 字數 4409 閱讀 8391

第四題還沒做…先貼前三個題的。

有一支

n個人的隊伍要過一座限重為

w的橋,我們規定這支隊伍過橋時只能分組過,即當一組全部過去後,下一組才能接著過。給定每個隊員的重量wi

和過橋時間ti

,一組人的過橋時間為花費時間最多的人的時間。問如何分組使得總的過橋時間最短。

input

100 3

24 60

10 40

18 50

output
42
資料範圍告訴我們應該考慮狀壓dp。用 d

p[s]

表示s中的人還未過河所用的時間,則有:dp

[s]=

maxt(a),w(a)分別表示通過的時間最大值和重量總和。

現在問題轉化為如何列舉集合的子集。如果用樸素的列舉只能拿到70分左右。從《挑戰程式設計競賽》上學到的乙個方法則可以降低複雜度:

sub = s;

do while (sub > 1)

這樣處理sub就列舉了2s

。總的複雜度可以用:∑1

≤i≤n

(ni)

2i打個表就知道能o(能過)…

#include 

using

namespace

std;

int dp[1

<<18], w, n;

int w[20], t[20];

int a[1

<<18], m[1

<<18];

int dfs(int s)

while (sap > 1);

//cout << s << " --> " << dp[s] << endl;

return dp[s];

}int main()

定義

f為斐波那契數列,被定義為:f0

=0,f

1=1f

n=fn

−1+f

n−2,

n>1而

g為乙個序列,定義為:gi

=∑a1

+a2+

...+

am=i

,ak>0∏

j≤mf

aj對於給定的n,求

gnmod109+

7。input

3
output
5
3=

1+1+

1f1×

f1×f

1=1=

2+1f

2×f1

=1=1

+2f1

×f2=

1=3f

3=21

+1+1

+2=5

首先看樣例解釋很容易發現乙個遞推式:gn

=∑1≤

i≤nf

i×gn

−i打表找規律會發現 ∀i

≥3,g

i=2g

i−1+

gn−2

。現在來證明一下:首先可以證明g1

=1,g

2=2⇒

g1+g

2=g3

+1,然後用歸納法2g

n−1+

gn−2

=∑1≤

i≤n−

12fi

gn−1

−i+∑

1≤i≤

n−2f

ign−

2−i=

∑1≤i

≤n−3

fi(2

gn−1

−i+g

n−2−

i)+2

fn−1

g0+2

fn−2

g1+f

n−2g

0=∑1

≤i≤n

−3fi

gn−i

+2fn

−1+3

fn−2

(1)2

fn−1

+3fn

−2=2

fn−2

+fn−

1+fn

=∑n−

2≤i≤

nfig

n−i因此:(1

)=gn

原命題得證。然後只需要矩陣[2

110]

做快速冪取模就好了。注意特判。

#include 

using

namespace

std;

struct matrix

friend matrix operator * (const matrix &a, const matrix &b)

};matrix i()

matrix power(const matrix &a, long

long n)

int main()

if (n == 1)

matrix m; m.a[1][1] = 2, m.a[1][2] = 1, m.a[2][1] = 1;

m = power(m, n-1);

cout

<< m.a[1][1] << endl;

return

0;}

給定

n個回文串,s1

,s2,

...,

sn。求有多少有序整數對 (i

,j) 使得si

sj仍為回文串。

input

7

2 aa

3 aba

3 aaa

6 abaaba

5 aaaaa

4 abba

output
14
當時考場上sdf乙個女選手怒而碾過orz……

我們用s−1

表示s的反串。容易知道「穿脫原則」: (a

b)−1

=b−1

a−1 在這裡成立。

考慮兩個回文串a,

b,根據定義有:a=

a−1,

b=b−

1⇒ba

=b−1

a−1滿足題目中條件為:ab

=(ab

)−1按照穿脫原則展開:ab

=b−1

a−1也就是:ab

=ba所以原問題轉化為了求ab

=ba的對數。考慮用多項式雜湊:ha

sh(a

b)=h

ash(

a)×b

ase|

b|+h

ash(

b)ha

sh(b

a)=h

ash(

b)×b

ase|

a|+h

ash(

a)ha

sh(a

)bas

e|a|

−1=h

ash(

b)ba

se|b

|−1可以看到兩側都變成了只含有乙個量的表示式,成功地將兩個量的關係轉化成了乙個量的性質,除法可以用模大素數下的乘法逆元處理,因此就可以丟進hash算了。

然而乙個問題是這樣做衝突嚴重。如果懶得寫拉鍊怎麼辦呢?乙個有趣的方法是考慮ab

=ba必然有a[

|a|]

=b[|

b|],而且他們是最高位,計算hash的時候乘了乙個巨大的數。因此我們可以把hash值乘上這一位的ascii,就可以很大程度避免衝突了。

至於base的選取..親測37效果最好…不知道為什麼,可能是資料的緣故吧…

#include 

using

namespace

std;

long

long mod = 2016122203ll, base = 37;

long

long power(long

long a, long

long n)

long

long inv(long

long a)

long

long hash_val(char str)

maplong, int> hash_set;

int n, w;

char str[2000005];

long

long cnt = 0;

inline

int read()

return a;

}inline

void read(char str)

str[i] = '\0';

}int main()

cout

<< cnt*2+n << endl;

return

0;}

2011多校九部分解題報告

1005 hdu3924題意每個樹有三個子樹,求第n個數的形狀。先求出不同個數的x方法數,然後先計算所有x的個數,然後不斷地遞迴算出左中右三個子樹的個數。rejudge了。注意左子樹相同時,中子樹的個數多的不一事實上在中子樹個數少的後面,因為此時要看左子樹的狀態 rejudge後wa include...

2020 4 19個人賽部分解題與補題報告

題意 給n,若有n個數能按規定的排序方式輸出 1,若不可以輸出反例 類似於冒泡法排序,但沒有內層排序 只有n 1或n 2的時候可以正確排序 include include include using namespace std intmain else cout 2 3 1 return0 view...

第三部分 POJ 1007 解題報告

poj 1007 dna sorting 問題描述 序列 未排序程度 的乙個計算方式是元素亂序的元素對個數。例如 在單詞序列 daabec 中,因為d大於右邊四個單詞,e大於c,所以計算結果為5。這種計算方法稱為序列的逆序數。序列 aacedgg 逆序數為1 e與d 近似排序,而序列 zwqm 逆序...