热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

洛谷P4705玩游戏(生成函数+多项式运算)

题面传送门题解妈呀这辣鸡题目调了我整整三天……最后发现竟然是因为分治\(NTT\)之后的多项式长度不是\(2\)的幂导致把多项式的值存下来的时候发生了一些玄学错误……玄学到了我\(WA\)

题面

传送门

题解

妈呀这辣鸡题目调了我整整三天……最后发现竟然是因为分治\(NTT\)之后的多项式长度不是\(2\)的幂导致把多项式的值存下来的时候发生了一些玄学错误……玄学到了我\(WA\)的点全都是\(WA\)\(2\)的幂次行里……

看到这种题目二话不说先推倒

\[ \begin{aligned} [x^k]Ans &={1\over nm}\sum_{i=1}^n\sum_{j=1}^m\left(a_i+b_j\right)^k\\ &={1\over nm}\sum_{i=1}^n\sum_{j=1}^m\sum_{p=0}^k{k\choose p}{a_i}^p{b_j}^{k-p}\\ &={k!\over nm}\sum_{p=0}^k{\sum_{i=1}^n{a_i}^p\over p!}{\sum_{j=1}^m{b_j}^{k-p}\over (k-p)!}\\ \end{aligned} \]

然后这就被画成了一个卷积的形式

定义两个多项式\(A(x)=\sum_{i=0}^\infty x^i\sum_{j=1}^n{a_j}^i\),和\(B(x)=\sum_{i=0}^\infty x^i\sum_{j=1}^m{b_j}^i\),只要我们能求出这两个多项式的系数,然后一通乱搞之后就能求出\(Ans\)

然后继续推倒

\[ \begin{aligned} A(x) &=\sum_{i=0}^\infty x^i\sum_{j=1}^n{a_j}^i\\ &=\sum_{j=1}^n\sum_{i=0}^\infty {a_j}^ix^i\\ &=\sum_{i=1}^n{1\over 1-a_ix}\\ &=\sum_{i=1}^n {a_i}^0+{a_i}^1x^1+{a_i}^2x^2+... \end{aligned} \]

所以……这玩意儿该咋算啊……

我们设

\[ \begin{aligned} G(x) &=\sum_{i=1}^n{-a_i\over 1-a_ix}\\ &=\sum_{i=1}^n-{a_i}^1-{a_i}^2x-{a_i}^3x^2-...\\ \end{aligned} \]

那么就有\(A(x)=-xG(x)+n\)

然而我还是不会算\(G\)啊……

那就继续推倒

\[ \begin{aligned} G(x) &=\sum_{i=1}^n{-a_i\over 1-a_ix}\\ &=\sum_{i=1}^n\ln'\left(1-a_ix\right)\\ &=\ln'\left(\prod_{i=1}^n (1-a_ix)\right) \end{aligned} \]

分治\(NTT\)就行啦

然后没有然后了

我错了多项式比计算几何难调多了

//minamoto
#include
#define R register
#define fp(i,a,b) for(R int i=(a),I=(b)+1;iI;--i)
#define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
using namespace std;
char buf[1<<21],*p1=buf,*p2=buf;
inline char getc(){return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++;}
int read(){
    R int res,f=1;R char ch;
    while((ch=getc())>'9'||ch<'0')(ch=='-')&&(f=-1);
    for(res=ch-'0';(ch=getc())>='0'&&ch<='9';res=res*10+ch-'0');
    return res*f;
}
char sr[1<<21],z[20];int C=-1,Z=0;
inline void Ot(){fwrite(sr,1,C+1,stdout),C=-1;}
void print(R int x){
    if(C>1<<20)Ot();if(x<0)sr[++C]='-',x=-x;
    while(z[++Z]=x%10+48,x/=10);
    while(sr[++C]=z[Z],--Z);sr[++C]='\n';
}
const int N=(1<<18)+5,P=998244353,Gi=332748118;
inline int add(R int x,R int y){return x+y>=P?x+y-P:x+y;}
inline int dec(R int x,R int y){return x-y<0?x-y+P:x-y;}
inline int mul(R int x,R int y){return 1ll*x*y-1ll*x*y/P*P;}
int ksm(R int x,R int y){
    R int res=1;
    for(;y;y>>=1,x=mul(x,x))if(y&1)res=mul(res,x);
    return res;
}
vectorr[21];int rt[2][N<<1],inv[N],fac[N],ifac[N],lim,d;
inline void init(R int len){lim=1,d=0;while(lim>1]>>1)|((i&1)<<(d-1));
    }
    inv[0]=inv[1]=fac[0]=fac[1]=ifac[0]=ifac[1]=1;
    fp(i,2,262144){
        fac[i]=mul(fac[i-1],i),
        inv[i]=mul(P-P/i,inv[P%i]),
        ifac[i]=mul(ifac[i-1],inv[i]);
    }
    for(R int t=(P-1)>>1,i=1,x,y;i<=262144;i<<=1,t>>=1){
        x=ksm(3,t),y=ksm(Gi,t);
        rt[1][i]=rt[0][i]=1;
        fp(k,1,i-1){
            rt[1][k+i]=mul(rt[1][k+i-1],x),
            rt[0][k+i]=mul(rt[0][k+i-1],y);
        }
    }
}
int rev[N];
void NTT(int *A,int ty){
    fp(i,0,lim-1)if(i>1),init(len<<1);
    static int A[N],B[N];
    fp(i,0,len-1)A[i]=a[i],B[i]=b[i];
    fp(i,len,lim-1)A[i]=B[i]=0;
    NTT(A,1),NTT(B,1);
    fp(i,0,lim-1)A[i]=mul(A[i],mul(B[i],B[i]));
    NTT(A,0);
    fp(i,0,len-1)b[i]=dec(add(b[i],b[i]),A[i]);
    fp(i,len,lim-1)b[i]=0;
}
void Ln(int *a,int *b,int len){
    static int A[N],B[N];
    fp(i,1,len-1)A[i-1]=mul(a[i],i);A[len-1]=0;
    Inv(a,B,len),init(len<<1);fp(i,len,lim-1)A[i]=B[i]=0;
    NTT(A,1),NTT(B,1);
    fp(i,0,lim-1)A[i]=mul(A[i],B[i]);
    NTT(A,0);
    fp(i,1,len-1)b[i]=mul(A[i-1],inv[i]);b[0]=0;
    fp(i,len,lim-1)b[i]=0;
}
int D[25][N];
void solve(int *a,int d,int l,int r){
    if(l==r)return D[d][0]=1,D[d][1]=P-a[l],void();
    int mid=(l+r)>>1;
    solve(a,d,l,mid),solve(a,d+1,mid+1,r),init(r-l+1+1);
    static int A[N],B[N];
    fp(i,0,mid-l+1)A[i]=D[d][i];fp(i,mid-l+2,lim-1)A[i]=0;
    fp(i,0,r-mid)B[i]=D[d+1][i];fp(i,r-mid+1,lim-1)B[i]=0;
    NTT(A,1),NTT(B,1);
    fp(i,0,lim-1)A[i]=mul(A[i],B[i]);
    NTT(A,0);
    fp(i,0,r-l+1)D[d][i]=A[i];
    fp(i,r-l+2,lim-1)D[d][i]=0;
}
int a[N],b[N],ak[N],bk[N];
int n,m,t;
void calc(int *a,int *b,int n,int t){
    static int A[N],B[N];
    solve(a,1,1,n);
    init(t+1);int len=lim;
    fp(i,0,n)A[i]=D[1][i];
    fp(i,n+1,len-1)A[i]=0;
    Ln(A,B,len);
    fp(i,1,len-1)B[i-1]=mul(B[i],i);B[len-1]=0;
    b[0]=n;
    fp(i,1,t)b[i]=mul(P-B[i-1],ifac[i]);
}
void Mul(int *a,int *b){
    init(t<<1);
    NTT(a,1),NTT(b,1);
    fp(i,0,lim-1)a[i]=mul(a[i],b[i]);
    NTT(a,0);
    int invm=ksm(mul(n,m),P-2);
    fp(i,1,t)print(1ll*a[i]*fac[i]%P*invm%P);
}
int main(){
//  freopen("testdata.in","r",stdin);
    Pre();
    n=read(),m=read();
    fp(i,1,n)a[i]=read();
    fp(i,1,m)b[i]=read();
    t=read();
    calc(a,ak,n,t),calc(b,bk,m,t);
    Mul(ak,bk);
    return Ot(),0;
}

推荐阅读
  • 在1995年,Simon Plouffe 发现了一种特殊的求和方法来表示某些常数。两年后,Bailey 和 Borwein 在他们的论文中发表了这一发现,这种方法被命名为 Bailey-Borwein-Plouffe (BBP) 公式。该问题要求计算圆周率 π 的第 n 个十六进制数字。 ... [详细]
  • 问题描述现在,不管开发一个多大的系统(至少我现在的部门是这样的),都会带一个日志功能;在实际开发过程中 ... [详细]
  • Hanks博士是一位著名的生物技术专家,他的儿子Hankson对数学有着浓厚的兴趣。最近,Hankson遇到了一个有趣的数学问题,涉及求解特定条件下的正整数x,而不使用传统的辗转相除法。 ... [详细]
  • 本问题涉及在给定的无向图中寻找一个至少包含三个节点的环,该环上的节点不重复,并且环上所有边的长度之和最小。目标是找到并输出这个最小环的具体方案。 ... [详细]
  • 洛谷 P4009 汽车加油行驶问题 解析
    探讨了经典算法题目——汽车加油行驶问题,通过网络流和费用流的视角,深入解析了该问题的解决方案。本文将详细阐述如何利用最短路径算法解决这一问题,并提供详细的代码实现。 ... [详细]
  • 本题要求计算一组正整数的最小公倍数(LCM)。输入包括多组测试数据,每组数据首先给出一个正整数n,随后是n个正整数。 ... [详细]
  • 本文详细介绍了在Luat OS中如何实现C与Lua的混合编程,包括在C环境中运行Lua脚本、封装可被Lua调用的C语言库,以及C与Lua之间的数据交互方法。 ... [详细]
  • 二维码的实现与应用
    本文介绍了二维码的基本概念、分类及其优缺点,并详细描述了如何使用Java编程语言结合第三方库(如ZXing和qrcode.jar)来实现二维码的生成与解析。 ... [详细]
  • 本文通过C++语言实现了一个递归算法,用于解析并计算数学表达式的值。该算法能够处理加法、减法、乘法和除法操作。 ... [详细]
  • Android与JUnit集成测试实践
    本文探讨了如何在Android项目中集成JUnit进行单元测试,并详细介绍了修改AndroidManifest.xml文件以支持测试的方法。 ... [详细]
  • 本文介绍如何手动实现一个字符串连接函数,该函数不依赖于C语言的标准字符串处理函数,如strcpy或strcat。函数原型为void concatenate(char *dest, char *src),其主要作用是将源字符串src追加到目标字符串dest的末尾。 ... [详细]
  • linux网络子系统分析(二)—— 协议栈分层框架的建立
    目录一、综述二、INET的初始化2.1INET接口注册2.2抽象实体的建立2.3代码细节分析2.3.1socket参数三、其他协议3.1PF_PACKET3.2P ... [详细]
  • 在尝试加载支持推送通知的iOS应用程序的Ad Hoc构建时,遇到了‘no valid aps-environment entitlement found for application’的错误提示。本文将探讨此错误的原因及多种可能的解决方案。 ... [详细]
  • 本文通过分析一个具体的案例,探讨了64位Linux系统对32位应用程序的兼容性问题。案例涉及OpenVPN客户端在64位系统上的异常行为,通过逐步排查和代码测试,最终定位到了与TUN/TAP设备相关的系统调用兼容性问题。 ... [详细]
  • protobuf 使用心得:解析与编码陷阱
    本文记录了一次在广告系统中使用protobuf进行数据交换时遇到的问题及其解决过程。通过这次经历,我们将探讨protobuf的特性和编码机制,帮助开发者避免类似的陷阱。 ... [详细]
author-avatar
手机用户2702932415_836
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有