【模拟赛12.28】T1

Time Limit 2s
Memory Limit 512M
Description
从1到n中选k个互不相同的,问一起为边长能组成凸k边形的方案数
Input
一行,n,k
Output
一行答案对998244353取模
Sample

Input1
100 3
Output1
79625
Input2
100 4
Output2
3281225
Input3
100 5
Output3
72464552

Data Constraint
n≤109,k≤200n\leq 10^9,k\leq 200n109,k200


什么凸多边形。。。搞得很难的样子,就是求选取方案种数使得最小的k-1个数的和大于第k个
考虑O(nk)O(nk)O(nk)怎么做
Ans=(nk)−∑i=1n(n−i+1)fi,k−1Ans={n\choose k}-\sum_{i=1}^n (n-i+1)f_{i,k-1}Ans=(kn)i=1n(ni+1)fi,k1(最大的数>=除最大数的和=i)
fi,jf_{i,j}fi,j表示选j个拼i的方案数
假设选出来的a1&lt;a2&lt;⋯&lt;aka_1&lt;a_2&lt;\cdots&lt;a_ka1<a2<<ak
其差分d1,d2,⋯&ThinSpace;,dk&gt;0d_1,d_2,\cdots,d_k&gt;0d1,d2,,dk>0
那么(k−1)d1+(k−2)d2+⋯+dk−1=i(k-1)d_1+(k-2)d_2+\cdots+d_{k-1}=i(k1)d1+(k2)d2++dk1=i
因此这可以背包

考虑生成函数
fi,k−1=[xi]∏i=1k−1xi1−xif_{i,k-1}=[x^i]\prod_{i=1}^{k-1}\frac{x^i}{1-x^i}fi,k1=[xi]i=1k11xixi
因为id(i)=i+1id(i)=i+1id(i)=i+1的OGF是1(1−x)2\frac 1{(1-x)^2}(1x)21
∑i=1n(n−i+1)fi,k−1\sum_{i=1}^n (n-i+1)f_{i,k-1}i=1n(ni+1)fi,k1是个卷积
(nk)−Ans=[xn][1(1−x)2∏i=1k−1xi1−xi]=[xn−12k(k−1)][1(1−x)2∏i=1k−11−xi]{n\choose k}-Ans=[x^n][\frac1{(1-x)^2}\prod_{i=1}^{k-1}\frac{x^i}{1-x^i}]=[x^{n-\frac12k(k-1)}][\frac1{(1-x)^2\prod_{i=1}^{k-1}1-x^i}](kn)Ans=[xn][(1x)21i=1k11xixi]=[xn21k(k1)][(1x)2i=1k11xi1]
m=n−12k(k−1)m=n-\frac12k(k-1)m=n21k(k1)

我们发现下面的(1−x)2∏i=1k−11−xi(1-x)^2\prod_{i=1}^{k-1}1-x^i(1x)2i=1k11xi可以表示成1−G(x)1-G(x)1G(x)的形式
这样就可以用线性常系数齐次递推,设(nk)−Ans=F(x)=11−G(x){n\choose k}-Ans=F(x)=\frac 1{1-G(x)}(kn)Ans=F(x)=1G(x)1
G(x)G(x)G(x)的最高次项为xtx^txt
那么F(x)G(x)=F(x)−1F(x)G(x)=F(x)-1F(x)G(x)=F(x)1
又G(x)常数项为0,那么设{fn}\{f_n\}{fn}为F(x)的系数数列,{gn}\{g_n\}{gn}同理,有fn=∑i=1nfn−igif_n=\sum_{i=1}^n f_{n-i}g_ifn=i=1nfnigi,这可以看做一个递推
设关于F(x)的矩阵AAA
A=[f1f2⋮ft] A= \begin{bmatrix} f_1\\ f_2\\ \vdots\\ f_t\\ \end{bmatrix} A=f1f2ft
设其转移矩阵为TTT
T=[g1g2⋯gt−1gt10⋯0001⋯00⋮⋮⋱⋮⋮00⋯10] T= \begin{bmatrix} g_1 &amp; g_2 &amp; \cdots &amp; g_{t-1} &amp; g_t\\ 1 &amp; 0 &amp; \cdots &amp; 0 &amp; 0 \\ 0 &amp; 1 &amp; \cdots &amp; 0 &amp; 0\\ \vdots &amp; \vdots &amp; \ddots &amp; \vdots &amp; \vdots\\ 0 &amp; 0 &amp; \cdots &amp; 1 &amp; 0\\ \end{bmatrix} T=g1100g2010gt1001gt000
那么要求的fmf_mfm可以通过求ATm−tAT^{m-t}ATmt

假设我们要求TmT^mTm
但是t很大,m也很大
有一个叫做凯莱·哈密顿定理的东西
T的特征多项式r(λ)=det⁡(λI−T)r(\lambda)=\det(\lambda I-T)r(λ)=det(λIT)
r(T)=0r(T)=0r(T)=0
特殊的,对于上面这类型的矩阵,其特征多项式为r(x)=xt−∑i=1tgixt−iir(x)=x^t-\sum_{i=1}^tg_ix^{t-i}ir(x)=xti=1tgixtii

r(x)r(x)r(x)只有t项!
如果求出xmmod&ThinSpace;&ThinSpace;r(x)x^m\mod r(x)xmmodr(x)再把T带进去就可以把指数大大缩小
这个可以倍增+多项式取模求

假设已经求出了h(x)=xmmod&ThinSpace;&ThinSpace;r(x)h(x)=x^m\mod r(x)h(x)=xmmodr(x)
但是t很大怎么办
考虑回原式子,我们需要求的是[Ah(T)][n][Ah(T)][n][Ah(T)][n]
又有ft+i=(ATi)[n]f_{t+i}=(AT^i)[n]ft+i=(ATi)[n]
这样就只用求∑ft+i[xi]h(x)\sum f_{t+i}[x^i]h(x)ft+i[xi]h(x)即可
只用求逆弄出f的前2t位,取模搞出个h(x)h(x)h(x)就可以求答案了


多项式取模(求商)
∣f(x)∣|f(x)|f(x)表示f(x)f(x)f(x)的最高次数
假设要求A(x)mod&ThinSpace;&ThinSpace;B(x)A(x)\mod B(x)A(x)modB(x)
A(x)=B(x)C(x)+D(x)A(x)=B(x)C(x)+D(x)A(x)=B(x)C(x)+D(x),且∣D(x)∣&lt;∣B(x)∣|D(x)|&lt;|B(x)|D(x)<B(x)
∣A(x)∣=n,∣B(x)∣=m|A(x)|=n,|B(x)|=mA(x)=n,B(x)=m
A(1x)=B(1x)C(1x)+D(1x)A(\frac1x)=B(\frac1x)C(\frac1x)+D(\frac1x)A(x1)=B(x1)C(x1)+D(x1)
同时乘上xnx^nxn
xnA(x)=xmB(x)×xn−mC(x)+xnD(x)x^nA(x)=x^mB(x)\times x^{n-m}C(x)+x^nD(x)xnA(x)=xmB(x)×xnmC(x)+xnD(x)
xnA(x),xmB(x),xn−mC(x)x^nA(x),x^mB(x),x^{n-m}C(x)xnA(x),xmB(x),xnmC(x)都相当于将他们反过来
只有D(x)D(x)D(x)的前n-m项系数都是0,
两边同时mod&ThinSpace;&ThinSpace;xn−m\mod x^{n-m}modxnm
消去D′(x)D&#x27;(x)D(x)(这里用“′&#x27;”表示将其反过来的多项式)变为A′(x)=B′(x)C′(x)(mod&ThinSpace;&ThinSpace;xn−m)A&#x27;(x)=B&#x27;(x)C&#x27;(x)(\mod x^{n-m})A(x)=B(x)C(x)(modxnm)
C′(x)=A′(x)B′(x)mod&ThinSpace;&ThinSpace;xn−mC&#x27;(x)=\frac{A&#x27;(x)}{B&#x27;(x)}\mod x^{n-m}C(x)=B(x)A(x)modxnm用一个多项式求逆
然后再乘回去求出D(x)D(x)D(x)

#include<cstring>
#include<cstdio>
#include<algorithm>
#define mo 998244353
#define K 262144
#define ll long long
#define REP(i,a,b) for(int i=a,___=b;i<___;++i)
#define RED(i,a,b) for(int i=a,___=b;--i>=___;)
using namespace std;

int N,k,G[K],F[K],t,w[K],rev[K],D[K];
ll n,m;

ll qpow(ll a,ll i){
	ll r=1;for(;i;i>>=1,a=a*a%mo)if(i&1)r=r*a%mo;return r;
}
void adjust(int &N,int l){
	for(;N<l;N<<=1);for(;N>>1>=l;N>>=1);
}
void prep(){
	ll W=qpow(3,(mo-1)/K);w[0]=1;REP(i,1,K)w[i]=W*w[i-1]%mo;
}
void ntt(int *a){
	REP(i,1,N){
		rev[i]=(rev[i>>1]>>1)+(i&1)*(N>>1);
		if(rev[i]<i)swap(a[i],a[rev[i]]);
	}ll T;
	for(int h=1,m=2,g=1;h<N;h=m,m<<=1,g++)REP(i,0,h)for(int j=i,k;j<N;j+=m)
		T=1ll*w[(K>>g)*i]*a[k=h+j],a[k]=(a[j]-T)%mo,a[j]=(a[j]+T)%mo;
}
void intt(int *a){
	REP(i,1,N>>1)swap(a[i],a[N-i]);ntt(a);
	ll n=qpow(N,mo-2);REP(i,0,N)a[i]=n*a[i]%mo;
}
void inv(int *a){
	static int b[K],c[K],n;n=N;
	REP(i,1,N+N)b[i]=c[i]=0;
	b[0]=qpow(a[0],mo-2);
	for(N=2;N<=n;){
		REP(i,0,N)c[i]=a[i];N<<=1;
		ntt(c);ntt(b);
		REP(i,0,N)b[i]=(2-1ll*b[i]*c[i])%mo*b[i]%mo;
		intt(b);REP(i,N>>1,N)b[i]=0;
	}N>>=1;REP(i,0,N)a[i]=b[i];
}
void mod(int *a,int na){
	static int c[K],d[K],nc,nb;
	nb=t;nc=na-nb+1;
	if(na<nb)return;
	REP(i,0,nc)c[i]=a[na-1-i],d[i]=D[i];
	adjust(N,nc+nc-1);REP(i,nc,N)d[i]=c[i]=0;
	ntt(c);ntt(d);REP(i,0,N)c[i]=1ll*c[i]*d[i]%mo;
	intt(c);
	adjust(N,na);REP(i,nc,N)c[i]=0;
	REP(i,0,nb)d[i]=G[i];REP(i,nb,N)d[i]=0;
	ntt(c);ntt(d);REP(i,0,N)c[i]=1ll*c[i]*d[i]%mo;
	intt(c);
	REP(i,0,na)a[i]=(a[i]-c[na-1-i])%mo;
}
//倍增用递归版的会更快
int qmod(ll m,int *a,int *r){
	if(m<t){r[m]=1;return m+1;}
	int l=qmod(m/2,a,r);adjust(N,l<<=1);
	ntt(r);REP(i,0,N)r[i]=1ll*r[i]*r[i]%mo;intt(r);
	if(m&1){RED(i,N,0)r[i+1]=r[i];r[0]=0;}else --l;
	mod(r,l);return min(l,t-1);
}
int c(int n,int m){
	int r=1;REP(i,1,m+1)r=1ll*r*qpow(i,mo-2)%mo*(n+1-i)%mo;return r;
}

int main(){
	scanf("%lld %d",&n,&k);
	if(n<k){printf("0");return 0;}
	int C=c(n,k);
	if(n<k*(k-1)/2){printf("%d",C);return 0;}
	prep();
	G[0]=G[2]=1;G[1]=mo-2;t=3;
	REP(i,1,k){
		RED(j,t,0)G[i+j]=(G[i+j]-G[j])%mo;t+=i;
	}N=1;adjust(N,t+t);
	REP(i,0,N)F[i]=G[i],D[i]=G[i];inv(F);
	n-=k*(k-1)/2;m=n-t+1;
	if(n<t+t){
		printf("%d",(1ll*C+mo-F[n])%mo);
		return 0;
	}
	//没有对其操作是因为特征多项式要反过来,再翻一次就恢复原样
	inv(D);//先预先反过来求个逆,不然倍增一次次求太慢
	static int r[K];
	REP(i,0,t+t)r[i]=0;
	qmod(m,G,r);
	int ans=0;
	REP(i,0,t)ans=(ans+1ll*r[i]*F[t-1+i])%mo;
	printf("%d",(1ll*C+mo-ans)%mo);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值