zoukankan      html  css  js  c++  java
  • LOJ #6512 [雅礼集训2018 Day8]C (多项式、牛顿迭代、图论、组合计数、DP)

    题目链接

    https://loj.ac/p/6512

    题解

    经典的烷烃计数,曾经被我搬到校内男人八题出了,下面挂我的题解
    (代码是今天才写的,出题的时候为了凑压轴题拉了份标程把这题出上了QAQ)

    代码

    #include<bits/stdc++.h>
    #define llong long long
    #define mkpr make_pair
    #define x first
    #define y second
    #define iter iterator
    #define riter reverse_iterator
    #define y1 Lorem_ipsum_
    #define tm dolor_sit_amet_
    using namespace std;
    
    inline int read()
    {
    	int x = 0,f = 1; char ch = getchar();
    	for(;!isdigit(ch);ch=getchar()) {if(ch=='-') f = -1;}
    	for(; isdigit(ch);ch=getchar()) {x = x*10+ch-48;}
    	return x*f;
    }
    
    const int mxN = 1<<19;
    const int lgN = 19;
    const int P = 998244353;
    
    llong quickpow(llong x,llong y)
    {
    	llong cur = x,ret = 1ll;
    	for(int i=0; y; i++)
    	{
    		if(y&(1ll<<i)) {y-=(1ll<<i); ret = ret*cur%P;}
    		cur = cur*cur%P;
    	}
    	return ret;
    }
    llong mulinv(llong x) {return quickpow(x,P-2);}
    
    namespace FFT
    {
    	const int G = 3;
    	llong aux1[mxN+3],aux2[mxN+3],aux3[mxN+3],aux4[mxN+3];
    	int fftid[mxN+3]; llong sexp[mxN+3];
    	int getdgr(int n) {int ret = 1; while(ret<=n) ret<<=1; return ret;}
    	void init_fftid(int dgr)
    	{
    		for(int i=1; i<dgr; i++) fftid[i] = (fftid[i>>1]>>1)|((i&1)*(dgr>>1));
    	}
    	void ntt(int dgr,int coe,llong poly[],llong ret[])
    	{
    		init_fftid(dgr);
    		if(poly==ret) {for(int i=0; i<dgr; i++) if(i<fftid[i]) swap(ret[i],ret[fftid[i]]);}
    		else {for(int i=0; i<dgr; i++) ret[i] = poly[fftid[i]];}
    		for(int i=1; i<dgr; i<<=1)
    		{
    			llong tmp = quickpow(G,(P-1)/(i<<1)); if(coe==-1) {tmp = mulinv(tmp);}
    			sexp[0] = 1ll; for(int j=1; j<i; j++) sexp[j] = sexp[j-1]*tmp%P;
    			for(int j=0; j<dgr; j+=(i<<1))
    			{
    				for(llong *k=ret+j,*kk=sexp; k<ret+i+j; k++,kk++)
    				{
    					llong x = *k,y = (*kk)*k[i]%P;
    					*k = x+y>=P?x+y-P:x+y;
    					k[i] = x-y<0ll?x-y+P:x-y;
    				}
    			}
    		}
    		if(coe==-1)
    		{
    			llong tmp = mulinv(dgr); for(int i=0; i<dgr; i++) ret[i] = ret[i]*tmp%P;
    		}
    	}
    	void polymul(int dgr,llong poly1[],llong poly2[],llong ret[])
    	{
    		memset(poly1+dgr,0,sizeof(llong)*dgr); memset(poly2+dgr,0,sizeof(llong)*dgr);
    		ntt(dgr<<1,1,poly1,aux1); ntt(dgr<<1,1,poly2,aux2);
    		for(int i=0; i<(dgr<<1); i++) ret[i] = aux1[i]*aux2[i]%P;
    		ntt(dgr<<1,-1,ret,ret);
    	}
    	void polyinv(int dgr,llong poly[],llong ret[])
    	{
    		memset(ret,0,sizeof(llong)*(dgr<<1)); ret[0] = mulinv(poly[0]);
    		for(int i=1; i<dgr; i<<=1)
    		{
    			ntt(i<<2,1,ret,aux3);
    			for(int j=0; j<(i<<2); j++) aux4[j] = j<(i<<1)?poly[j]:0ll;
    			ntt(i<<2,1,aux4,aux4);
    			for(int j=0; j<(i<<2); j++) aux4[j] = (2ll*aux3[j]-aux3[j]*aux3[j]%P*aux4[j]%P+P)%P;
    			ntt(i<<2,-1,aux4,aux4);
    			for(int j=0; j<(i<<1); j++) ret[j] = aux4[j];
    		}
    	}
    }
    using FFT::ntt;
    using FFT::getdgr;
    using FFT::polymul;
    using FFT::polyinv;
    
    int dgr; llong Inv2,Inv6,Inv24;
    llong aux1[mxN+3],aux2[mxN+3],aux3[mxN+3],aux4[mxN+3],aux5[mxN+3];
    llong a[mxN+3],b[mxN+3],c[mxN+3],d[mxN+3];
    
    void calca()
    {
    	a[0] = 1ll;
    	for(int i=1; i<dgr; i<<=1)
    	{
    		int tot = (i<<2)-1;
    		ntt(i<<2,1,a,aux1);
    		for(int j=0; j<(i<<2); j++) {aux2[j] = (aux1[j]*aux1[j]%P*aux1[j]%P+3ll*aux1[(2*j)&tot]*aux1[j]%P+2ll*aux1[(3*j)&tot])*Inv6%P;}
    		ntt(i<<2,-1,aux2,aux2); memset(aux2+(i<<1),0,sizeof(llong)*(i<<1));
    		for(int j=(i<<1)-2; j>=0; j--) {aux2[j+1] = aux2[j];} aux2[0] = 1ll;
    		for(int j=0; j<(i<<1); j++) aux2[j] = (aux2[j]-a[j]+P)%P;
    		for(int j=0; j<(i<<2); j++) {aux3[j] = (aux1[j]*aux1[j]%P+aux1[(2*j)&tot])%P*Inv2%P;}
    		ntt(i<<2,-1,aux3,aux3); memset(aux3+(i<<1),0,sizeof(llong)*(i<<1));
    		for(int j=(i<<1)-2; j>=0; j--) {aux3[j+1] = aux3[j];} aux3[0] = P-1ll;
    		polyinv(i<<1,aux3,aux4);
    		polymul(i<<1,aux2,aux4,aux5);
    		for(int j=0; j<(i<<1); j++) {a[j] = (a[j]-aux5[j]+P)%P;}
    	}
    }
    
    int main()
    {
    	int T = read();
    	dgr = 1<<17; Inv2 = mulinv(2ll),Inv6 = mulinv(6ll),Inv24 = mulinv(24ll);
    	calca();
    	int tot = (dgr<<2)-1;
    	ntt(dgr<<2,1,a,aux1);
    	for(int i=0; i<(dgr<<2); i++) {b[i] = (aux1[i]*aux1[i]%P*aux1[i]%P*aux1[i]%P+6ll*aux1[i]*aux1[i]%P*aux1[(2*i)&tot]%P+3ll*aux1[(2*i)&tot]*aux1[(2*i)&tot]%P+8ll*aux1[(3*i)&tot]*aux1[i]%P+6ll*aux1[(4*i)&tot])%P*Inv24%P;}
    	ntt(dgr<<2,-1,b,b); memset(b+dgr,0,sizeof(llong)*dgr*3);
    	for(int i=dgr-2; i>=0; i--) b[i+1] = b[i]; b[0] = 1ll;
    	for(int i=0; i<(dgr<<2); i++) {d[i] = (aux1[i]*aux1[i]%P-2ll*aux1[i]%P+aux1[(2*i)&tot]+P)*Inv2%P;}
    	ntt(dgr<<2,-1,d,d); memset(d+dgr,0,sizeof(llong)*dgr*3);
    	for(int i=0; i<(dgr<<2); i++) {c[i] = (b[i]-d[i]+(i&1?0ll:a[i/2])+P)%P;} c[0] = (c[0]-1ll+P)%P;
    	while(T--) {printf("%lld
    ",c[read()]);}
    	return 0;
    }
    
  • 相关阅读:
    名字 地址 路由
    截断二进制指数退避
    硬件地址 软件地址
    基带信号 调制
    非对称数字用户线
    码分复用 码分多址
    时分复用 帧长度
    多模光纤 单模光纤
    码间串扰 奈氏准则 香农公式
    flask 文件下载 文件服务器 请求参数 函数修饰符
  • 原文地址:https://www.cnblogs.com/suncongbo/p/14477668.html
Copyright © 2011-2022 走看看