NTT 51nod 1514 美妙的序列

2022-05-06 14:57:11 字數 1555 閱讀 6774

題意: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 long

long

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 }

view code

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...