ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

[loj3640]细菌

2022-02-18 09:00:47  阅读:182  来源: 互联网

标签:le ln int d% loj3640 a0 细菌 mod


将过程逆序,问题即转换为以下形式——

从$(a,b,c)$出发,每步移动到周围六个格子之一,求$d$步内不离开长方体的方案数

显然每一维可以通过生成函数合并,不妨仅考虑其中一维,问题也即

从$(0,a)$出发,每步移动到右上/右下的格子,$\forall 0\le i\le d$求$i$步内与$y=0,n+1$不交的方案数

可以参考[hdu7069],容斥得答案即
$$
f(a)-\sum_{l\ge 1,l\equiv 1(mod\ 2)}\Big(f(n'-ln'-a)+f(ln'+n'-a)\Big)+\sum_{l\ge 1,l\equiv 0(mod\ 2)}\Big(f(ln'+a)+f(a-ln')\Big)
$$
(其中$n'=n+1,f(a)$表示$i$步从$(0,a)$到$\forall j\in [1,n],(i,j)$的方案数)

关于$f(a)$,考虑枚举向上的步数$x$​,不难得到
$$
f(a)=\sum_{0\le x\le i,1\le a+2x-i\le n}{i\choose x}=\sum_{\max(\lceil\frac{i-a+1}{2}\rceil,0)\le x\le \min(\lfloor\frac{i+n-a}{2}\rfloor,i)}{i\choose x}
$$
要求其范围非空,即解得$1-i\le a\le i+n$

换言之,$l$的范围是$o(\frac{i}{n})$的,暴力枚举的复杂度为$o(\frac{d^{2}}{n})$

另外,关于$f(a)$的计算,可以调换$i$和$l$的枚举顺序,并在$i$增加时维护区间

另一方面,当$d$较小时,可以直接暴力$o(nd)$递推

按$n\le \sqrt{d}$和$n>\sqrt{d}$分别处理,时间复杂度为$o(d\sqrt{d})$

结合合并三维时的生成函数,总复杂度为$o(d\sqrt{d}+d\log d)$,可以通过

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 #define N 120005
  4 #define M (1<<19)
  5 #define K 400
  6 #define mod 998244353
  7 #define ll long long
  8 int n,a,b,c,a0,b0,c0,L,R,s,ans,fac[N],inv[N],rev[M],A[M],B[M],C[M],mi[M],f[N][K];
  9 int qpow(int n,int m){
 10     int s=n,ans=1;
 11     while (m){
 12         if (m&1)ans=(ll)ans*s%mod;
 13         s=(ll)s*s%mod,m>>=1;
 14     }
 15     return ans;
 16 }
 17 void ntt(int *A,int n,int p=0){
 18     for(int i=0;i<n;i++)
 19         if (i<rev[i])swap(A[i],A[rev[i]]);
 20     for(int i=2;i<=n;i<<=1){
 21         int s=qpow(3,(mod-1)/i);
 22         if (p)s=qpow(s,mod-2);
 23         mi[0]=1;
 24         for(int k=1;k<(i>>1);k++)mi[k]=(ll)mi[k-1]*s%mod;
 25         for(int j=0;j<n;j+=i)
 26             for(int k=0;k<(i>>1);k++){
 27                 int x=A[j+k],y=(ll)A[j+k+(i>>1)]*mi[k]%mod;
 28                 A[j+k]=(x+y)%mod,A[j+k+(i>>1)]=(x-y+mod)%mod;
 29             }
 30     }
 31     if (p){
 32         int s=qpow(n,mod-2);
 33         for(int i=0;i<n;i++)A[i]=(ll)A[i]*s%mod;
 34     }
 35 }
 36 int Com(int n,int m){
 37     return (ll)fac[n]*inv[m]%mod*inv[n-m]%mod;
 38 }
 39 void Calc(int *A,int a,int a0,int p=0){
 40     int i0=max(max(1-a0,a0-a),0);
 41     L=max((i0-a0>>1)+1,0),R=min((i0+a-a0>>1),i0),s=0;
 42     for(int x=L;x<=R;x++)s=(s+Com(i0,x))%mod;
 43     if (!p)A[i0]=(A[i0]+s)%mod;
 44     else A[i0]=(A[i0]-s+mod)%mod;
 45     for(int i=i0+1;i<=n;i++){
 46         int L0=max((i-a0>>1)+1,0),R0=min((i+a-a0>>1),i);
 47         s=(s<<1)%mod,s=(s-Com(i-1,R)+mod)%mod;
 48         if (L)s=(s+Com(i-1,L-1))%mod;
 49         while (L<L0)s=(s-Com(i,L++)+mod)%mod;
 50         while (R<R0)s=(s+Com(i,++R))%mod;
 51         if (!p)A[i]=(A[i]+s)%mod;
 52         else A[i]=(A[i]-s+mod)%mod;
 53     }
 54 }
 55 void calc(int *A,int a,int a0){
 56     if ((ll)a*a<=n){
 57         memset(f,0,sizeof(f));
 58         A[0]=f[0][a0]=1;
 59         for(int i=1;i<=n;i++)
 60             for(int j=1;j<=a;j++){
 61                 if (j>1)f[i][j]=(f[i][j]+f[i-1][j-1])%mod;
 62                 if (j<n)f[i][j]=(f[i][j]+f[i-1][j+1])%mod;
 63                 A[i]=(A[i]+f[i][j])%mod;
 64             }
 65         return;
 66     }
 67     int n0=a+1;
 68     Calc(A,a,a0);
 69     for(int l=1;;l+=2){
 70         int k=n0-l*n0-a0;
 71         if (k<1-n)break;
 72         Calc(A,a,k,1);
 73     }
 74     for(int l=1;;l+=2){
 75         int k=l*n0+n0-a0;
 76         if (k>n+a)break;
 77         Calc(A,a,k,1);
 78     }
 79     for(int l=2;;l+=2){
 80         int k=l*n0+a0;
 81         if (k>n+a)break;
 82         Calc(A,a,k);
 83     }
 84     for(int l=2;;l+=2){
 85         int k=a0-l*n0;
 86         if (k<1-n)break;
 87         Calc(A,a,k);
 88     }
 89 }
 90 int main(){
 91     fac[0]=inv[0]=inv[1]=1;
 92     for(int i=1;i<N;i++)fac[i]=(ll)fac[i-1]*i%mod;
 93     for(int i=2;i<N;i++)inv[i]=(ll)(mod-mod/i)*inv[mod%i]%mod;
 94     for(int i=1;i<N;i++)inv[i]=(ll)inv[i-1]*inv[i]%mod;
 95     for(int i=0;i<M;i++)rev[i]=(rev[i>>1]>>1)+((i&1)*(M>>1));
 96     scanf("%d%d%d%d%d%d%d",&n,&a,&b,&c,&a0,&b0,&c0);
 97     calc(A,a,a0),calc(B,b,b0),calc(C,c,c0);
 98     for(int i=0;i<=n;i++){
 99         A[i]=(ll)A[i]*inv[i]%mod;
100         B[i]=(ll)B[i]*inv[i]%mod;
101         C[i]=(ll)C[i]*inv[i]%mod;
102     }
103     ntt(A,M),ntt(B,M),ntt(C,M);
104     for(int i=0;i<M;i++)A[i]=(ll)A[i]*B[i]%mod*C[i]%mod;
105     ntt(A,M,1),ans=(ll)A[n]*fac[n]%mod;
106     printf("%d\n",ans);
107     return 0;
108 } 
View Code

 

标签:le,ln,int,d%,loj3640,a0,细菌,mod
来源: https://www.cnblogs.com/PYWBKTDA/p/15907184.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有