简单序列问题
Description
给定 \(n,p\),求满足以下条件的长度为 \(n\) 序列 \(a\) 的数量。
- \(1\le a_1\le a_2\le \cdots\le a_n\le n\)。
- \(\forall k\in[1,n),\sum_{i=1}^k{a_i}>\sum_{i=n-k+2}^{n}{a_i}\)。
数据范围:\(n\le333333\),\(9\times10^8\le p\le10^9\)。
时间范围:\(2500\operatorname{ms}\)。
Solution
好题。我标好题的次数可不多。——我国著名化学家 \(\text{wzl}\) 先生。
- 为了满足条件一,考虑将 \(a\) 差分,设差分后数组为 \(b\),且 \(b_i=a_{i+1}-a_i\)。
- 设 \(m=\lceil \frac{n}{2}\rceil\)。可以发现,当 \(k=m\) 时满足答案,则其余 \(k\) 都满足答案。
- 分类讨论,这里只详细讨论 \(n\) 为奇数的情况。
- 当 \(n\) 为奇数时, 条件二转化为 \(\sum_{i=1}^{m-1}{i\times b_i}+\sum_{i=m}^{n-1}{(n-i+1)\times b_i}<s\),其中 \(s=\sum_{i=0}^{n}{b_i}\)。
- 考虑生成函数。 设
\[\begin{aligned}F(x)&=\frac{1}{(1-x)(1-x^m)[(1-x^2)\ldots(1-x^{m-1})]^2}\\
&=\left(\frac{(1-x^{m+1})(1-x^{m+2})\ldots}{(1-x)(1-x^2)(1-x^3)\ldots}\right)^2\times(1-x)\times(1-x^m)\end{aligned}\]
- 观察分式上方,可以发现当 \(p+q\ge n\) 时,\((1-x^{p})(1-x^{q})\equiv{1-x^p-x^q}\pmod{x^n}\),可以通过前缀和求出。
观察分式下方,发现是五边形数,\((1-x)(1-x^2)\ldots=\sum_{i=0}^{\infty}{(-1)^ix^{\frac{i(3i\pm1)}{2}}}\),\(O(n)\) 项内只有约 \(O(\sqrt n)\) 项非 \(0\),可以 \(O(n\sqrt n)\) 求两次得到,避免 MTT。 - 答案即为 \(\sum_{i=0}^{n-1}{(n-i)\times [x^i]F(x)}\)。
- 当 \(n\) 为偶数时,同理
\[F(x)=\left(\frac{(1-x^{m+1})(1-x^{m+2})\ldots}{(1-x)(1-x^2)(1-x^3)\ldots}\right)^2\times(1-x)
\]
- 时间复杂度为 \(O(n\sqrt n)\),需要卡常。
Code
#include<cstdio>
using namespace std;
const int maxn=400010;
int n,m,MLY,F[maxn],cnt,ans,k[maxn],G[maxn];
inline int mod(int x){
if(x<0)return x+MLY;
if(x>=MLY)return x-MLY;
return x;
}
inline void GetInv(){
for(int i=1;i<n;++i)
for(int j=1;k[j]<=i&&j<=cnt;++j)
F[i]=mod(F[i]-F[i-k[j]]*G[j]);
}
int main(){
freopen("sequence.in","r",stdin);
freopen("sequence.out","w",stdout);
scanf("%d%d",&n,&MLY);
m=(n+1)>>1;F[0]=1;
for(int i=m+1;i<n;++i)F[i]=MLY-2;
k[0]=0;G[0]=1;
for(int i=1;i*(3*i-1)/2<n;++i){
if(i*(3*i-1)/2<n){k[++cnt]=i*(3*i-1)/2;G[cnt]=(i%2)?-1:1;}
if(i*(3*i+1)/2<n){k[++cnt]=i*(3*i+1)/2;G[cnt]=(i%2)?-1:1;}
}
GetInv();GetInv();
for(int i=n-1;i;--i)F[i]=mod(F[i]-F[i-1]);
if(n&1)for(int i=n-1;i>=m;--i)F[i]=mod(F[i]-F[i-m]);
for(int i=0;i<n;++i)ans=mod(ans+1ll*(n-i)*F[i]%MLY);
printf("%d",ans);
return 0;
}

浙公网安备 33010602011771号