題意:1~n 的全排列中,有多少個排列滿足任意從中間切成兩段後,左邊段的最大值大於右邊段的最小值?
例如:n為3時有3種
2 3 1
3 1 2
3 2 1
解釋:比如 2 3 1
(2) (3 1) 1比2小
(2 3) (1) 1比2小
都滿足上面的條件。
3 2 1
(3)(2 1) 1比3小
(32)(1) 1比3小
都滿足上面的條件。
而2 1 3不滿足,因為(2 1)(3),3比左邊所有的數都大。
***********************************=分割線***********************************=
首先序列為美妙的等價於不存在(1<=i令f[n]為長度為n的答案
則:f[0]=0
f[i]=i!-sigma(f[j]*(i-j)!) 0<=j我們將其變形
sigma(f[j]*(i-j)!) = i! i > 0, j=0~i
sigma(f[j]*(i-j)!) = 0 i = 0, j=0~i
令g(x)=sigma(i!*x^i),f(x)=sigma(f[i]*x^i)
f(x)*g(x)=g(x)-1 (減一為i = 0的情況)
f(x)=(g(x)-1)/g(x)=1-1/g(x)
多項式求逆即可
1 #include2 #include3 typedef longview codelong
ll;4
using
namespace
std;
5const
int n = 262144, k = 17;6
intn, m, i, k;
7int a[n+10], b[n+10], tmp[n+10], tmp2[n+10];8
int p = 998244353, g = 3, g[k+1], ng[k+10], inv[n+10
], inv2;
9int pow(int a,int b)
10void ntt(int*a,int n,int
t)15
for(int d=0;(1
24if(t==-1)for(int i=0,j=inv[n];ip;25}
26//
給定a,求a的逆元b
27void getinv(int*a,int*b,int
n)29 getinv(a,b,n>>1
);30
int k=n<<1
,i;31
for(i=0;ia[i];
32for(i=n;i0
;33 ntt(tmp,k,1),ntt(b,k,1
);34
for(i=0;i)
38 ntt(b,k,-1
);39
for(i=n;i0;40
}41intmain()
59return0;
60 }
51nod1514 美妙的序列 分治NTT
顯然,不合法的情況要存在序列被分成值域為 1,i 與 i 1,r 兩部分.不妨採用容斥的方法來減去所有不合法的情況.令 f i 表示 1 i 構成的合法序列數目.那麼不合法的情況一定可以表示為 f j times i j 即前 j 個數組成的連通塊合法,然後第乙個不合法位點為 j,j 1 由於每一次...
51nod 1514 美妙的序列
某個1 n的排列如果滿足 在1 n 1 這些位置後面將序列斷開,使得總可以從右邊找到乙個數,並且該數不大於左邊的所有數,則稱該序列為 美妙的 給出n,求長度為n的 美妙的序列 的數量。首先第一步,讀懂題!換句話說,就是當左邊所有數都比右邊的最小值小時不合法。那麼就按照題意dp,考慮容斥,列舉從哪個點...
51 nod 最高的獎勵
有n個任務,每個任務有乙個最晚結束時間以及乙個對應的獎勵。在結束時間之前完成該任務,就可以獲得對應的獎勵。完成每乙個任務所需的時間都是1個單位時間。有時候完成所有任務是不可能的,因為時間上可能會有衝突,這需要你來取捨。求能夠獲得的最高獎勵。input 第1行 乙個數n,表示任務的數量 2 n 500...