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;
    }
    
  • 相关阅读:
    【LeetCode OJ】Remove Element
    【LeetCode OJ】Remove Duplicates from Sorted Array
    【LeetCode OJ】Swap Nodes in Pairs
    【LeetCode OJ】Merge Two Sorted Lists
    【LeetCode OJ】Remove Nth Node From End of List
    【LeetCode OJ】Two Sum
    【LeetCode OJ】Majority Element
    最长公共子序列问题
    php fopen与file_get_contents的区别
    PHP 技巧集合
  • 原文地址:https://www.cnblogs.com/suncongbo/p/14477668.html
Copyright © 2011-2022 走看看