慶祝一下,,,第乙個我自己做出來的,,,多項式的題(沒辦法,我太弱
雖然用了2個小時才想出來,但這畢竟是0的突破……
首先宣告,雖然我寫的題解很長,但是大部分都是證明和廢話
第一步,轉化題意(用時30min):
乙個1~n的全排列$p$,如果存在$i
問所有p的所有排列方案,最後聯通塊的大小的乘積,的和。
因為原題中$a$是隨機的實數,所以說我們可以不用考慮有$a_i=a_j$的情況。
因為最後用到的只有相對的大小關係,所以可以直接轉化成乙個1~n的排列$p$。
其實很多時間都花在"誒,是這個意思嗎,不會啊","哦,不對,看錯題了"。
第二步,找規律推性質(用時50min):
我們發現,乙個聯通塊,一定是$l$到$r$連續的一段。
假如說,$a$和$b$在同乙個聯通塊內(令$a
我們來證明這種情況是不存在的。
首先,$p[b]
那麼$p[a]>p[b]$,但是他們在同乙個聯通塊內,
所以一定存在乙個位置$x$滿足$xb,p[x]>p[a]$
那麼$x$一定與$c$直接相連,所以證出矛盾。
同理,我們可以證到乙個聯通塊的$p$也是連續的一段。
但是我不是這麼找到這個性質的,因為我上面的方法只是證明了這個性質,但是如果我猜不到這個性質……
我按照套路思考,每個聯通塊找乙個代表員好了,找誰呢,那就$p$最小的那個吧。
我們把點放在乙個平面上,第$i$個點的座標是$(i,p[i])$。
我們按照$p$從小到大,加入每個點。
首先,$p$最小的那個點加入的時候,我們考慮找它所在的聯通塊的點。
找到乙個滿足$p[j]>p[i]$的最大的$j$,那麼$i$到$j$這個連續區間的所有點都在同乙個聯通塊內。
(把這些點分成$p[x]p[j]>p[i]$兩種情況討論就可以了)
然後$然後我們把這些點刪掉,再找到$p$最小的那個點,遞迴下去。
我們發現,我們把乙個n*n的矩形,一次一次的減去乙個聯通塊所在的"勢力範圍",其實是一次一次砍掉了右邊的一條和下面的一條,剩下的還是乙個矩形。
如圖:
其中淡粉色是乙個聯通塊的勢力範圍,$t$是這個聯通塊$p$最大的點,$k$是這個聯通塊最靠左(就是編號最小)的點。
我們再找下乙個聯通塊的時候,下乙個聯通塊勢力範圍一定是在白色部分。
所以下乙個聯通塊的$p$最小的點的一定有$p[x]>p[t]$,編號最大的點$x
於是我們兩個性質都找到啦。
有了這兩個性質之後,我們可以發現,乙個聯通塊$[l,r]$,一定滿足:$p[l],p[l+1],....,p[r-1],p[r]$一定是$n-l+1,n-(l+1)+1,....,n-r+1$的乙個排列。
同時$p[1],p[2],....,p[r]$一定是$n,n-1,...,n-r+1$的乙個排列。
同時$[l,r-1]$中不存在$x$滿足$p[1],p[2],....,p[x]$是$n,n-1,....,n-x+1$的乙個排列,否則就可以分出$[l,x],[x+1,r]$兩個聯通塊了。
也就是說,如果我們稱滿足$p[1],p[2],....,p[x]$是$n,n-1,....,n-x+1$的乙個排列的$x$是好的,那麼每個$x$都一定是乙個聯通塊的右端點。
第三步,推式子(用時40min):
有了上面的幾個性質,我們可以開始列$dp$方程了。
我們令$f(n)$表示1~n的乙個排列,除$n$位置外,不存在其他位置是好的,的方案數。
那麼$f(0)=0,f(1)=1$
$f(n)=n!-\sum\limits_^ i! f(n-i)$
令$g(n)=n!$,特別地,我們規定$g(0)=1$
那麼$f(n)=g(n)-\sum\limits_^ g(i) f(n-i)$
把$\sum$移到左邊,可以得到$\sum\limits_^ g(i) f(n-i) = g(n)$
我們發現這是乙個卷積形式$f*g+1=g$。(因為$f(0)=0,g(0)=1$)
令$dp(i)$表示前$i$個數,並且$i$是乙個聯通塊右端點,的貢獻。規定$dp(0)=1$
列舉上乙個聯通塊的右端點,那麼有:
$dp(n)=\sum\limits_^ (n-i) f(n-i) dp(i)$
令$h(n)=nf(n)$。$h(0)=0$
$dp(n)=\sum\limits_^ h(n-i) dp(i)$
又是乙個卷積形式$dp=dp*h+1$。(因為$h(0)=0,dp(0)=1$)
於是兩次多項式求逆就可以解決問題啦。
//serene#include#include#include#include#include#includeusing namespace std;
#define ll long long
#define db double
#define for(i,a,b) for(int i=(a);i<=(b);++i)
#define rep(i,a,b) for(int i=(a);i>=(b);--i)
const ll mod=998244353,b=3;
const int maxn=1e7+7;
ll n,g[maxn],h[maxn],ginv[maxn],hinv[maxn],x[maxn];
templatevoid read(t& aa)
ll qp(ll x,ll k)
return rs;
}ll finv(ll x)
ll qp1(ll x,ll k)
void rader(ll f,ll len)
if(j>1,a,b);
ll n=1;for(;n<=(n<<1);n<<=1);
for(i,0,n-1) x[i]=a[i]; for(i,n,n) x[i]=b[i]=0;
fft(x,n,1); fft(b,n,1);
for(i,0,n) b[i]=b[i]*(2-b[i]*x[i]%mod+mod)%mod;
fft(b,n,-1); for(i,n,n) b[i]=0;
}int main()
校門外的樹
描述 某校大門外長度為 l的馬路上有一排樹,每兩棵相鄰的樹之間的間隔都是 1公尺。我們可以把馬路看成乙個數軸,馬路的一端在數軸 0的位置,另一端在 l的位置 數軸上的每個整數點,即0,1,2 l,都種有一棵樹。馬路上有一些區域要用來建地鐵,這些區域用它們在數軸上的起始點和終止點表示。已知任一區域的起...
校門外的樹
某校大門外長度為l的馬路上有一排樹,每兩棵相鄰的樹之間的間隔都是1公尺。我們可以把馬路看成乙個數軸,馬路的一端在數軸0的位置,另一端在l的位置 數軸上的每個整數點,即0,1,2,l,都種有一棵樹。由於馬路上有一些區域要用來建地鐵。這些區域用它們在數軸上的起始點和終止點表示。已知任一區域的起始點和終止...
校門外的樹
校門外的樹 題目描述 某校大門外長度為l的馬路上有一排樹,每兩棵相鄰的樹之間的間隔都是1公尺。我們可以把馬路看成乙個數軸,馬路的一端在數軸0的位置,另一端在l的位置 數軸上的每個整數點,即0,1,2,l,都種有一棵樹。由於馬路上有一些區域要用來建地鐵。這些區域用它們在數軸上的起始點和終止點表示。已知...