首先我們可以簡化一下條件,顯然只要滿足相鄰元素滿足限制即可。即對於任意的相鄰的 i,
j 滿足 ma
x>=|x
i−xj
| 考慮如果我們已經知道排列的順序,那麼我們很容易統計這種順序下的答案:設 s
=∑n−
1i=1
max ,則相當於選
n 個非負整數,加和不大於 x−
1−s的方案數。經典的隔板法得 方案數 (x
−1−s
+nn)
。s小於 n2
,現在我們需要對於每個
s 算出有幾種方案。可以 dp
,考慮從小到大不斷插入,現在插入的是當前的最大值,這樣比較好處理。f[
i][s
][j]
,j表示有
j個間隙待插入,
s 表示其他規定不再插入的位置對s的貢獻和。這樣轉移時就考慮插入後新多出來的空,是否規定不再插入。還有往邊界插的特殊情況需要考慮。
複雜度o(n
4)
#include
#include
#include
using namespace std;
typedef long long ll;
const int maxn=100105;
int n,m,mod,f[2][10105][115],ans;// f[i][s][j]
ll inv[maxn],fac[maxn],fac_inv[maxn];
ll c(int n,int
m)int main()
(f[(i&1)^1][s][j+1]+=f_now*2
%mod)%=mod;
(f[(i&1)^1][s+(i+1)][j]+=f_now*2
%mod)%=mod;}}
for(int
s=0;s
<=n*n&&s
<=m-n;s++) (ans+=c(m-s,n)*f[n&1][s][0]%mod)%=mod;
printf("%d\n",ans);
return
0;}
2023年8月10號提高組T3 樹
給你一棵大小為n的有根樹,每個點有點權,要求完成以下操作 v x y把點x的權值變成y e x把有根樹的根變為x q x查詢點x的子樹的最小值 第一行兩個整數n,m,表示點數和運算元。接下來n行,每行兩個數f,v,第i行的兩個數表示i的父親和i的權值,且保證f接下來m行,每行表示乙個操作。對於每個q...
2023年8月16日提高組T3 旅館
有一間旅館,旅館內有n間排成一排的房間,一開始全為空。現在有m個要求 1 d表示詢問旅館內是否有連續d間空房間,有的話則輸出最小的乙個r,滿足從r開始連續d間房間均為空,同時會有人入住這d間房。若無法被滿足,則輸出0.2 l r表示把 l,r 內的房間全部設為空。第一行兩個整數n,m.接下來m行,每...
2023年8月7日提高組T3 選數
給出n個數a i 現在可以在其中任意選出若干個數,問有多少種選擇方案,使得這幾個數可以分成兩個和相等的集合。第一行是乙個正整數n,第二行每行n個正整數。輸出乙個數,表示方案數。對於30 的資料,n 10.對於100 的資料,n 20,a i 100000000.by bpm 略難每個數字前可以填1 ...