序列 2020聯考 dp

2021-10-25 04:50:15 字數 2087 閱讀 8711

可以發現對於乙個素數最多2

22 個數擁有

然後這兩個數連邊

發現向前只有 1

11 條邊

那麼轉化成森林方案數

首先計算一棵樹的方案數

f is

:i個節

點素數佔

用集合為

s樹的方

案數f_: i 個節點素數占用集合為s樹的方案數

fis​:i

個節點素

數占用集

合為s樹

的方案數

轉移要麼連邊要麼自己加然後gis

:i個節

點素數佔

用集合為

s森林的

方案數g_: i個節點素數占用集合為s森林的方案數

gis​:i

個節點素

數占用集

合為s森

林的方案

數樹和樹之間是不同的,所以每次轉移欽定新加入樹的最後乙個點在最後,排列組合即可

注意**實現

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

using

namespace std;

#define ll long long

ll read()

while

('0'

<=c&&c<=

'9') x=

(x<<3)

+(x<<1)

+(c^48)

,c=getchar()

;return

!f?x:

-x;}

#define mp make_pair

const

int maxn=(1

<<6)

;const

int mod=

(int)(

1e9+7)

;int f[25]

[maxn+5]

,h[maxn+5]

,g[25

][maxn+5]

;int m,a[10]

,c[30][

30];int

bitcnt

(int x)

intmain()

if(tt!=1)

a[++m]=1

;for

(int s=

0;s<

;s++

)for

(int i=

2;i<=m+

1;i++)}

memcpy

(h,f[i]

,sizeof

(f[i]))

;for

(int s=

0;s<

;s++)}

memcpy

(f[i]

,h,sizeof

(f[i]))

;}f[1][

0]=0

,g[0][

0]=1

;int ans=0;

for(

int i=

1;i<=

2*m+

1;i++

)for

(int s=

1;s<

;s++

) ans=

(ans+g[i]

[s])

%mod;

}printf

("%d\n"

,ans)

;return0;

}//2446

//2462 x

2020多校聯考 樹

沒有定根就非常的離譜,後來告訴根直接就是 1 先考慮鏈上怎麼做,顯然維護乙個單調棧,求出第乙個比當前數大的位置,然後倍增即可。再放在樹上怎麼做?依舊維護單調棧,但這次不能暴力地彈掉棧頂元素了,因為這樣的複雜度是假的。因為單調棧有單調性,所以直接在單調棧內二分出單調棧彈得不能再彈的位置,然後修改 to...

2020多校聯考 手套

有兩個可重集 a 和 b 每個集合裡有若干元素,每種元素有若干個。可以選擇從 a 集中等概率隨機選 x 個到 c 集 從 b 中等概率隨機選擇 y 個到 d 使得一定會使 c 和 d 有交。最小化 x y 在 x y 相等時最小化 x 因為要使得一定有交,所以考慮選了一定數目後,沒有交的最壞情況。最...

2020多校聯考 簡單題

確實是簡單題。邊權和最小顯然是最小生成樹。對於一條非樹邊,加到樹裡面一定會構成乙個環,那麼環上的樹邊的邊權就一定不能超過這條非樹邊。所以對最小生成樹進行重鏈剖分,對於一條非樹邊 u i,v i 對鏈 u i to v i 進行 modify 維護乙個最小值。而對於一條非樹邊要想成為樹邊,就至少需要把...