可以發現對於乙個素數最多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 維護乙個最小值。而對於一條非樹邊要想成為樹邊,就至少需要把...