3.15 模拟赛

Posted yyc-jack-0920

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了3.15 模拟赛相关的知识,希望对你有一定的参考价值。

T1 

 

T2 小R的箱子

 

T3 绯红之王

题目大意:

已知数列$a$,求$sumlimits_{i=1}^n {a_i}^k$

思路:

很久以前讲过的题,调了一年才搞出来

首先设$f_k=sumlimits_{i=1}^n {a_i}^k$ , $g_k$表示对于所有$C_n^k$种选择的方法,$g_k=$所有方法内各个数相乘的和

例如数列中有四个数$a,b,c,d$ 则

$g_0=1$

$g_1=a+b+c+d$

$g_2=ab+ac+ad+bc+bd+cd$

$g_3=abc+abd+acd+bcd,g_4=abcd$

我们可以发现

$f_2=f_1 * g_1 - 2g_2$

$f_3=f_2 * g_1 - f_1* g_2 + 3g_3$

$f_4=f_3*g_1-f_2*g_2+f_1*g_3-4g_4$

发现下标为偶数的$g$都变成了其相反数,而且这是一个$f_0$在变化的分治$NTT$形式

那么我们将$f_0$设为0,在$cdq$到$l==r$时,再加上这个$n*g_n$贡献

现在考虑如何计算$g$数组,因为$g_i$是齐次轮换对称式 可以通过计算两部分再合并

例如$h_0=1,h_1=a+b+c,h_2=ab+ac+bc,h_3=abc$

$t_0=1,t_1=d+e+f,t_2=de+df+ed,t_3=def$

则$g_0=h_0*t_0=1$

$g_1=h_0*t_1+h_1*t_0$

$g_2=h_0*t_2+h_1*t_1+h_2*t_0$

$......$

这样可以维护一个类似线段树的结构来计算$g$,即一开始每个点有一个自己的多项式$1,a_i$

然后一层一层往上合并,计算出$g$后再用分治$NTT$来计算$f$

技术图片
 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<cstdlib>
 5 #include<cmath>
 6 #include<algorithm>
 7 #include<queue>
 8 #include<vector>
 9 #include<map>
10 #include<set>
11 #define ll long long
12 #define db double
13 #define inf 2139062143
14 #define MAXN 800100
15 #define MOD 998244353
16 #define rep(i,s,t) for(register int i=(s),i##__end=(t);i<=i##__end;++i)
17 #define dwn(i,s,t) for(register int i=(s),i##__end=(t);i>=i##__end;--i)
18 #define ren for(register int i=fst[x];i;i=nxt[i])
19 #define pb(i,x) vec[i].push_back(x)
20 #define pls(a,b) (1LL*a%MOD+b%MOD+MOD)%MOD
21 #define mns(a,b) (1LL*a%MOD-b%MOD+MOD)%MOD
22 #define mul(a,b) ((ll)(1LL*(a))%MOD*(b)%MOD)%MOD
23 using namespace std;
24 inline int read()
25 {
26     int x=0,f=1;char ch=getchar();
27     while(!isdigit(ch)) {if(ch==-) f=-1;ch=getchar();}
28     while(isdigit(ch)) {x=x*10+ch-0;ch=getchar();}
29     return x*f;
30 }
31 int n,rev[MAXN],l2[MAXN],pw[MAXN],A[MAXN],B[MAXN],aa[MAXN];
32 int g[MAXN],f[MAXN];
33 vector<int> vec[MAXN];
34 int q_pow(int bas,int t,int res=1)
35 {
36     for(;t;bas=mul(bas,bas),t>>=1)
37         if(t&1) res=mul(res,bas);return res;
38 }
39 void ntt(int *a,int n,int f)
40 {
41     rep(i,0,n-1) if(i<rev[i]) swap(a[i],a[rev[i]]);
42     for(int i=1;i<n;i<<=1)
43     {
44         int wn=pw[i<<1];if(f==-1) wn=q_pow(wn,MOD-2);
45         for(int j=0;j<n;j+=i<<1)
46         {
47             int w=1,x,y;
48             for(int k=0;k<i;k++,w=mul(w,wn))
49                 x=a[k+j],y=mul(a[i+j+k],w),a[j+k]=pls(x,y),a[i+j+k]=mns(x,y);
50         }
51     }
52     if(f==1) return ;int nv=q_pow(n,MOD-2);
53     rep(i,0,n-1) a[i]=mul(a[i],nv);
54 }
55 void solve(int *a,int *b,int lmt)
56 {
57     ntt(a,lmt,1);ntt(b,lmt,1);rep(i,0,lmt-1) a[i]=mul(a[i],b[i]);
58     ntt(a,lmt,-1);
59 }
60 void Div(int l,int r,ll lmt=0)
61 {
62     if(l==r) return ;int mid=(l+r)>>1,lg;
63     Div(l,mid);Div(mid+1,r);lg=l2[r-l+1]+1,lmt=1<<lg;
64     rep(i,0,lmt-1) rev[i]=(rev[i>>1]>>1)|((i&1)<<(lg-1)),A[i]=B[i]=0;
65     rep(i,0,vec[l].size()-1) A[i]=vec[l][i];
66     rep(i,0,vec[mid+1].size()-1) B[i]=vec[mid+1][i];
67     solve(A,B,lmt);
68     vec[l].clear();vec[mid+1].clear();
69     rep(i,0,lmt-1) vec[l].push_back(A[i]);
70 }
71 void cdq(int l,int r)
72 {
73     if(l==r) {f[l]=pls(f[l],mul(g[l],l));return ;}
74     int mid=l+r>>1,lmt=r-l+1;cdq(l,mid);
75     int t=l2[lmt]+1;lmt=1<<t;
76     rep(i,0,lmt-1) rev[i]=(rev[i>>1]>>1)|((i&1)<<(t-1)),A[i]=B[i]=0;
77     rep(i,l,mid) A[i-l]=f[i];rep(i,1,r-l) B[i-1]=g[i];
78     solve(A,B,lmt);rep(i,mid+1,r) f[i]=pls(f[i],A[i-l-1]);
79     cdq(mid+1,r);
80 }
81 int main()
82 {
83     n=read();rep(i,1,n) aa[i]=read();rep(i,2,n<<2) l2[i]=l2[i>>1]+1;
84     rep(i,1,n<<2) pw[i]=q_pow(3,(MOD-1)/i);
85     rep(i,1,n) vec[i].push_back(1),vec[i].push_back(aa[i]);
86     Div(1,n);rep(i,0,n) g[i]=vec[1][i];
87     rep(i,0,n) if(!(i&1)) g[i]=-g[i];
88     cdq(0,n);rep(i,1,n) printf("%d
",f[i]);
89 }
View Code

 

以上是关于3.15 模拟赛的主要内容,如果未能解决你的问题,请参考以下文章

GDOI2016模拟3.15圈地游戏

cocos2d-x 3.15(lua) 在Xcode8.2+下模拟器运行崩溃问题 iOS simulator crash when running cocos2d-x 3.15 lua project

Catfish(鲶鱼) Blog V1.3.15 代码审计

「学习笔记」3.15代码学习

3.15

上周热点回顾(3.9-3.15)