#4701. Con

题目描述

题解

设 $b_i$ 表示 $i$ 出现的次数

化式子,得$$\sum_{i=1}^{max}\sum_{j=1}^{max}b_ib_j2^{ij}$$$$\sum_{i=1}^{max}\sum_{j=1}^{max}b_ib_j\sqrt2^{(i+j)^2-i^2-j^2}$$

于是我们设 $A_i=b_i\sqrt2^{-i^2}$,卷积后每一项乘上$\sqrt2^{i^2}$即可

效率: $O(nlogn)$

代码

#include <bits/stdc++.h>
#define LL long long
using namespace std;
const int N=4e5+5,P=998244353,I=116195171;
int n,m,a[N],s,A[N],r[N],t=1,p,G[2]={3,(P+1)/3};
int X(int x){return x>=P?x-P:x;}
int K(int x,LL y){
    int z=1;
    for (;y;y>>=1,x=1ll*x*x%P)
        if (y&1) z=1ll*z*x%P;
    return z;
}
void Ntt(int *g,bool o){
    for (int i=0;i<t;i++)
        if (i<r[i]) swap(g[i],g[r[i]]);
    for (int wn,i=1;i<t;i<<=1){
        wn=K(G[o],(P-1)/(i<<1));
        for (int x,y,j=0;j<t;j+=(i<<1))
            for (int w=1,k=0;k<i;k++,w=1ll*w*wn%P)
                x=g[j+k],y=1ll*w*g[i+j+k]%P,
                g[j+k]=X(x+y),g[i+j+k]=X(x-y+P);
    }
    if (o)
        for (int i=0,v=K(t,P-2);i<t;i++)
            g[i]=1ll*v*g[i]%P;
}
int main(){
    cin>>n;int iv=K(I,P-2);
    for (int j,i=1;i<=n;i++){
        scanf("%d",&a[i]),m=max(m,a[i]);
        j=K(iv,1ll*a[i]*a[i]);
        A[a[i]]=X(A[a[i]]+j);
    }
    for (m=m+m+1;t<m+1;t<<=1,p++);
    for (int i=0;i<t;i++)
        r[i]=(r[i>>1]>>1)|((i&1)<<(p-1));
    Ntt(A,0);
    for (int i=0;i<t;i++)
        A[i]=1ll*A[i]*A[i]%P;
    Ntt(A,1);
    for (int i=0;i<m;i++)
        s=X(s+1ll*K(I,1ll*i*i)*A[i]%P);
    cout<<s<<endl;return 0;
}

 

posted @ 2020-02-03 17:17  xjqxjq  阅读(298)  评论(0编辑  收藏  举报