思路

超级麻烦。。。

写了一堆最后常数太大T飞了。。。

真的难受

发现solve函数可以不用把下一层复制上来,直接传指针就可以,下次再说写不写叭

思路

\[ans_k=\sum_{i=1}^n\sum_{j=1}^m (a_i+b_j)^k
\]

二项式定理拆一下式子

\[\begin{align}ans_k=&\sum_{i=1}^n\sum_{j=1}^m (a_i+b_j)^k\\=&\sum_{i=1}^n\sum_{j=1}^m\sum_{t=0}^k\left(\begin{matrix}k\\t\end{matrix}\right)a_i^{k-t}b_j^t\\=&\sum_{t=0}^k\left(\begin{matrix}k\\t\end{matrix}\right)\sum_{i=1}^na_i^{k-t}\sum_{j=1}^mb_j^t\\=&k!\sum_{r=0}^k(\sum_{i=1}^n\frac{a_i^r}{r!})(\sum_{j=1}^m\frac{b_j^r}{r!})\end{align}
\]

所以只要求出\(\sum_i a_i^k\)即可

对\(a_i\),设其生成函数\(A(x)=1+a_ix+a_i^2x^2+a_i^3x^3+\dots\)

\[A_k(x)=\sum_{i=0}^{\infty}a_k^ix^i=\frac{1}{1-a_kx}
\]

最后答案的生成函数\(G(x)\)就是\(\sum_{i=0}^n A_i(x)\)

然后一个常见套路就是把\(\frac{1}{x}\)用\(\ln 'x\)代替

所以有

\[G(x)=\sum_{i=1}^n \frac{1}{1-a_ix}=\sum_{i=1}^n \ln'(1-a_ix)
\]

但是这样依然无法快速计算

我们可以再设一个\(F(x)\)

\[F(x)=\sum_{i=1}^n (\ln(1-a_ix))'=\sum_{i=1}^n\frac{-a_i}{1-a_ix}\\
G(x)=\sum_{i=1}^n \frac{1}{1-a_ix}
\]

所以\(G(x)=-xF(x)+n\)

然后对于\(F(x)\),

\[F(x)=\sum_{i=1}^n (\ln(1-a_ix))'=(\ln(\prod_{i=1}(1-a_ix)))'
\]

分治加NTT就可以在\(O(n\log^2n)\)的时间内解决

常数过大T掉的代码

#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cctype>
#include <cstdlib>
#include <assert.h>
#define int long long
using namespace std;
const int MAXN = 600000;
const int MAXL = 100100;
const int G = 3;
const int invG = 332748118;
const int MOD = 998244353; const int InputBufferSize = 67108864;//输入缓冲区大小
const int OutputBufferSize = 67108864;//输出缓冲区大小 namespace input
{
char buffer[InputBufferSize],*s,*eof;
inline void init()
{
assert(stdin!=NULL);
s=buffer;
eof=s+fread(buffer,1,InputBufferSize,stdin);
}
inline bool read(int &x)
{
x=0;
int flag=1;
while(!isdigit(*s)&&*s!='-')s++;
if(eof<=s)return false;
if(*s=='-')flag=-1,s++;
while(isdigit(*s))x=x*10+*s++-'0';
x*=flag;
return true;
}
inline bool read(char* str)
{
*str=0;
while(isspace(*s))s++;
if(eof<s)return false;
while(!isspace(*s))*str=0,*str=*s,str++,s++;
*str=0;
return true;
}
} namespace output
{
char buffer[OutputBufferSize];
char *s=buffer;
inline void flush()
{
assert(stdout!=NULL);
fwrite(buffer,1,s-buffer,stdout);
s=buffer;
fflush(stdout);
}
inline void print(const char ch)
{
if(s-buffer>OutputBufferSize-2)flush();
*s++=ch;
}
inline void print(char* str)
{
while(*str!=0)print(char(*str++));
}
inline void print(int x)
{
char buf[25]= {0},*p=buf;
if(x<0)print('-'),x=-x;
if(x==0)print('0');
while(x)*(++p)=x%10,x/=10;
while(p!=buf)print(char(*(p--)+'0'));
}
} using namespace input;
using namespace output; int pow(int a,int b){
int ans=1;
while(b){
if(b&1)
ans=(1LL*ans*a)%MOD;
a=(1LL*a*a)%MOD;
b>>=1;
}
return ans;
}
void FFT(int *a,int n,int opt,int lim){
for(int i=0;i<n;++i){
int t=0;
for(int j=0;j<lim;++j)
if((i>>j)&1)
t|=(1LL<<(lim-j-1));
if(i<t)
swap(a[i],a[t]);
}
for(int i=2;i<=n;i<<=1){
int len=i/2;
int tmp=pow((opt)?G:invG,(MOD-1)/i);
for(int j=0;j<n;j+=i){
int arr=1;
for(int k=j;k<j+len;++k){
int t=(1LL*a[k+len]*arr)%MOD;
a[k+len]=(a[k]-t+MOD)%MOD;
a[k]=(a[k]+t)%MOD;
arr=(1LL*arr*tmp)%MOD;;
}
}
}
if(!opt){
int invN=pow(n,MOD-2);
for(int i=0;i<n;++i)
a[i]=1LL*a[i]*invN%MOD;
}
}
void mul(int *a,int *bx,int &at,int bt){
static int b[MAXN];
int lim=0,num=at+bt,logt;
while((1<<lim)<=(num+2))
lim++;
logt=lim;
lim=(1<<lim);
for(int i=0;i<lim;++i)
b[i]=bx[i];
FFT(a,lim,1,logt);
FFT(b,lim,1,logt);
for(int i=0;i<lim;++i)
a[i]=(1LL*a[i]*b[i])%MOD;
FFT(a,lim,0,logt);
for(int i=num+1;i<lim;++i)
a[i]=0;
at=num;
}
void inv(int *a,int *b,int &bt,int dep,int &midlen,int &logt){
if(dep==1){
b[0]=pow(a[0],MOD-2);
bt=0;
return;
}
inv(a,b,bt,(dep+1)>>1,midlen,logt);
static int tmp1[MAXN];
for(int i=0;i<dep;++i)
tmp1[i]=a[i];
while((dep<<1)>midlen)
midlen<<=1,logt++;
for(int i=dep;i<midlen;++i)
tmp1[i]=0;
FFT(tmp1,midlen,1,logt);
FFT(b,midlen,1,logt);
for(int i=0;i<midlen;++i)
b[i]=1LL*b[i]*(2-1LL*tmp1[i]*b[i]%MOD+MOD)%MOD;
FFT(b,midlen,0,logt);
for(int i=dep;i<midlen;++i)
b[i]=0;
bt=dep-1;
}
void jf(int *a,int &at){
for(int i=at;i>=0;--i)
a[i+1]=(1LL*a[i]*pow(i+1,MOD-2))%MOD;
a[0]=0;
at++;
}
void qd(int *a,int &at){
for(int i=0;i<at;++i)
a[i]=(1LL*a[i+1]*(i+1))%MOD;
a[at]=0;
at--;
}
void ln(int *a,int *b,int at,int &bt,int n){
int midlen=1,logt=0;
inv(a,b,bt,at+1,midlen,logt);
qd(a,at);
mul(b,a,bt,at);
jf(b,bt);
for(int i=n;i<=bt;++i)
b[i]=0;
bt=n-1;
}
int val[MAXL];
int P[20][MAXN],Pt[20];
void solve(int l,int r,int dep){
if(l==r){
for(int i=2;i<=Pt[dep];++i)
P[dep][i]=0;
P[dep][0]=1;
P[dep][1]=MOD-val[l];
Pt[dep]=1;
return;
}
int mid=(l+r)>>1;
solve(l,mid,dep+1);
for(int i=0;i<=Pt[dep+1];++i)
P[dep][i]=P[dep+1][i];
for(int i=Pt[dep+1]+1;i<=Pt[dep];++i)
P[dep][i]=0;
Pt[dep]=Pt[dep+1];
solve(mid+1,r,dep+1);
mul(P[dep],P[dep+1],Pt[dep],Pt[dep+1]);
}
int jc[MAXL],jc_inv[MAXL];
int n,m,t;
void initx(void){
jc[0]=1;
int up=max(max(n,m),t)+1;
for(int i=1;i<up;++i)
jc[i]=(1LL*jc[i-1]*i)%MOD;
jc_inv[up-1]=pow(jc[up-1],MOD-2);
for(int i=up-2;i>=0;--i){
jc_inv[i]=(1LL*jc_inv[i+1]*(i+1))%MOD;
}
}
void getf(int *b,int &bt,int n){
solve(1,n,0);
int midlen=1,midlog=0;
Pt[0]=max(n+1,1LL*t+1);
inv(P[0],b,bt,Pt[0]+1,midlen,midlog);
qd(P[0],Pt[0]);
mul(b,P[0],bt,Pt[0]);
for(int i=bt;i>=0;--i)
b[i+1]=MOD-b[i];
b[0]=n;
for(int i=0;i<=bt;++i){
b[i]=(1LL*b[i]*jc_inv[i])%MOD;
}
}
int ap[MAXN],bp[MAXN];
int ax[MAXL],bx[MAXL];
signed main(){
freopen("test.in","r",stdin);
freopen("test.out","w",stdout);
// scanf("%d %d",&n,&m);
init();
read(n);
read(m);
for(int i=1;i<=n;++i)
read(ax[i]);
// scanf("%d",&ax[i]);
for(int i=1;i<=m;++i)
read(bx[i]);
// scanf("%d",&bx[i]);
// scanf("%d",&t);
read(t);
initx();
for(int i=1;i<=n;++i)
val[i]=ax[i];
int apt=0,bpt=0;
getf(ap,apt,n);
for(int i=1;i<=m;++i)
val[i]=bx[i];
getf(bp,bpt,m);
mul(ap,bp,apt,bpt);
int n_inv=pow(n,MOD-2),m_inv=pow(m,MOD-2);
for(int i=1;i<=t;++i){
print(1LL*jc[i]*ap[i]%MOD*n_inv%MOD*m_inv%MOD);
print('\n');
}
flush();
return 0;
}

P4705 玩游戏的更多相关文章

  1. 洛谷 P4705 玩游戏 解题报告

    P4705 玩游戏 题意:给长为\(n\)的\(\{a_i\}\)和长为\(m\)的\(\{b_i\}\),设 \[ f(x)=\sum_{k\ge 0}\sum_{i=1}^n\sum_{j=1}^ ...

  2. Luogu P4705 玩游戏

    题目描述 Alice 和 Bob 又在玩游戏. 对于一次游戏,首先 Alice 获得一个长度为 ​ 的序列 ​,Bob 获得一个长度为 ​ 的序列 bb.之后他们各从自己的序列里随机取出一个数,分别设 ...

  3. 洛谷P4705 玩游戏 [生成函数,NTT]

    传送门 这是两个月之前写的题,但没写博客.现在回过头来看一下发现又不会了-- 还是要写博客加深记忆. 思路 显然期望可以算出总数再乘上\((nm)^{-1}\). 那么有 \[ \begin{alig ...

  4. [洛谷P4705]玩游戏

    题目大意:对于每个$k\in[1,t]$,求:$$\dfrac{\sum\limits_{i=1}^n\sum\limits_{j=1}^m(a_i+b_j)^k}{nm}$$$n,m,t\leqsl ...

  5. 洛谷 P4705 玩游戏

    题目分析 题目要求的是: \[ \sum_{i=1}^n\sum_{j=1}^m(a_i+b_j)^x(x\in [1,T]) \] 利用二项式定理化式子, \[ \begin{aligned} &a ...

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

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

  7. 原生JS实战:写了个一边玩游戏,一边记JS的API的游戏

    本文是苏福的原创文章,转载请注明出处:苏福CNblog:http://www.cnblogs.com/susufufu/p/5878913.html 本程序[一边玩游戏,一边记JS的API]是本人的个 ...

  8. bzoj4730: Alice和Bob又在玩游戏

    Description Alice和Bob在玩游戏.有n个节点,m条边(0<=m<=n-1),构成若干棵有根树,每棵树的根节点是该连通块内编号最 小的点.Alice和Bob轮流操作,每回合 ...

  9. 小易邀请你玩一个数字游戏,小易给你一系列的整数。你们俩使用这些整数玩游戏。每次小易会任意说一个数字出来,然后你需要从这一系列数字中选取一部分出来让它们的和等于小易所说的数字。 例如: 如果{2,1,2,7}是你有的一系列数,小易说的数字是11.你可以得到方案2+2+7 = 11.如果顽皮的小易想坑你,他说的数字是6,那么你没有办法拼凑出和为6 现在小易给你n个数,让你找出无法从n个数中选取部分求和

    小易邀请你玩一个数字游戏,小易给你一系列的整数.你们俩使用这些整数玩游戏.每次小易会任意说一个数字出来,然后你需要从这一系列数字中选取一部分出来让它们的和等于小易所说的数字. 例如: 如果{2,1,2 ...

随机推荐

  1. 理解JS原型和原型链

    本文通过对<JavaScript高级程序设计>第六章的理解,加上自己的理解,重组了部分内容,形成下面的文字. 理解了原型这个概念,你的JS世界会清明很多. 为什么要为JS创造原型这个概念 ...

  2. PySe-008-开启浏览器的手机模式

    以 Chrome 为例,通过设置 chromeoption 的参数即可实现启动浏览器后,开启手机模式.相应设置的源代码如下所示: chromeOptions = webdriver.ChromeOpt ...

  3. Windows下使用TeamViewer连接远程服务器,以及解决“远程桌面关闭后TeamViewer不能连接”的问题

    1.本地安装TeamViewer,完成后如下: 2.远程服务器也安装TeamViewer 在本地TeamViewer中得伙伴ID,输入远程的ID,弹出如下对话框,输入密码即可. 3.这时虽然可以连接, ...

  4. SQL Server 主库DML操作慢故障处理过程

    从某个时间开始,Cat监控到的数据发现,正式环境的Insert 表很慢,数据库用了AlwasON高可用(1个备库做了实时同步),特别是每天早上9:00--11:00,做活动的时候,下单的insert需 ...

  5. 使用springmvc进行文件的上传和下载

    文件的上传 SpringMVC支持文件上传组件,commons-fileupload,commons-fileupload依赖commons-io组件 配置步骤说明 第一步:导入包 commons-f ...

  6. webpack(4)-管理输出

    设置 HtmlWebpackPlugin html-webpack-plugin:它会用新生成的 index.html文件,替换我们的原有文件 plugins: [ new HtmlWebpackPl ...

  7. elasticsearch 之编译过程

    https://github.com/elastic/elasticsearch/blob/master/CONTRIBUTING.md 不同的版本需要指定JDK 可以下载openJDK版本到服务器上 ...

  8. Oracle 11g R2 Backup Data Pump(数据泵)之expdp/impdp工具

    Oracle Data Pump(以下简称数据泵)是Oracle 10g开始提供的一种数据迁移工具,同时也被广大DBA用来作为数据库的逻辑备份工具和体量较小的数据迁移工具.与传统的数据导出/导入工具, ...

  9. Java多线程处理List数据

    实例1: 解决问题:如何让n个线程顺序遍历含有n个元素的List集合 import java.util.ArrayList; import java.util.List; import org.apa ...

  10. Respone弹窗

    Response.Write("<script>window.open('default.aspx?iID=" + GridView1.DataKeys[GridVie ...