在 l d x f A K e f A K e ldxfAKefAKe ldxfAKefAKe的帮助下终于会这道题了
其实发现本身只是一个十进制
f
w
t
fwt
fwt裸题
但是由于奇特的模数
2
58
2^{58}
258没法直接搞
问题在于没有 ω 10 \omega_{10} ω10以及 i d w t idwt idwt的时候除 10 10 10没有逆元
首先逆元的问题可以发现
10
=
2
∗
5
,
5
10=2*5,5
10=2∗5,5有逆元
然后发现实际上由于模数是二的次方所以直接除以2也是对的
然后考虑如何处理
ω
10
\omega_{10}
ω10
考虑直接对每个数表示为维护一个多项式
∑
i
a
i
ω
10
i
\sum_{i}a_i\omega_{10}^i
∑iaiω10i
显然多项式长度只有10
然后就可以直接做十进制
f
w
t
fwt
fwt了
最后输出答案的问题
直接输出常数项肯定是错的
由于最后答案一定是个整数
可以考虑
ω
10
=
cos
π
/
5
+
i
sin
π
/
5
\omega_{10}=\cos_{\pi/5}+i\sin_{\pi/5}
ω10=cosπ/5+isinπ/5
然后带进
∑
i
a
i
ω
10
i
\sum_ia_i\omega_{10}^i
∑iaiω10i
可以直接把实部的实数系数加起来就是答案
即
a
0
+
(
a
1
−
a
2
+
a
3
−
a
4
−
a
6
+
a
7
−
a
8
+
a
9
)
/
4
−
a
5
a_0+(a_1-a_2+a_3-a_4-a_6+a_7-a_8+a_9)/4-a_5
a0+(a1−a2+a3−a4−a6+a7−a8+a9)/4−a5
中间可以不用取模,用 u n s i g n e d l o n g l o n g unsigned\ long\ long unsigned long long,最后模一次即可
#include<bits/stdc++.h>
using namespace std;
#define cs const
#define re register
#define fi first
#define se second
#define pii pair<int,int>
#define ll long long
#define bg begin
cs int RLEN=1<<20|1;
inline char gc(){
static char ibuf[RLEN],*ib,*ob;
(ib==ob)&&(ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
return (ib==ob)?EOF:*ib++;
}
inline int read(){
char ch=gc();
int res=0;bool f=1;
while(!isdigit(ch))f^=ch=='-',ch=gc();
while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
return f?res:-res;
}
template<class tp>inline void chemx(tp &a,tp b){a<b?a=b:0;}
template<class tp>inline void chemn(tp &a,tp b){a>b?a=b:0;}
typedef unsigned long long ull;
ull tmp[20];
cs int N=100005;
int n,mx;
cs ull inv5=57646075230342349ull;
cs ull mod=(1ll<<58);
struct plx{
ull a[10];
plx(){memset(a,0,sizeof(a));}
inline ull &operator [](cs int &k){return a[k];}
inline cs ull &operator [](cs int &k)const{return a[k];}
friend inline plx operator *(plx a,plx b){
for(int i=0;i<10;i++)if(a[i])
for(int j=0;j<10;j++)tmp[i+j]+=a[i]*b[j];
for(int i=0;i<10;i++)a[i]=tmp[i]+tmp[i+10],tmp[i]=tmp[i+10]=0;
return a;
}
inline ull val(){
ull ret=0;
ret+=(a[0]-a[5])*4;
ret+=a[1]-a[2]+a[3]-a[4]-a[6]+a[7]-a[8]+a[9];
return (ret>>2)%mod;
}
}f[N<<1];
inline plx ksm(plx a,int b){
plx ret;ret[0]=1;
for(;b;b>>=1,a=a*a)if(b&1)ret=ret*a;
return ret;
}
inline void fwt(plx *f,int lim,int kd){
ull tmp[10][20];
for(int mid=1;mid<lim;mid*=10)
for(int i=0;i<lim;i+=mid*10)
for(int j=0;j<mid;j++){
for(int k=0;k<10;k++){
memset(tmp[k],0,sizeof(tmp[k]));
for(int p=0;p<10;p++){
int mt=k*p%10;
if(kd==-1)mt=(10-mt)%10;
for(int l=0;l<10;l++)tmp[k][l+mt]+=f[i+j+p*mid][l];
}
for(int l=10;l<20;l++)tmp[k][l-10]+=tmp[k][l];
}
if(kd==1)for(int k=0;k<10;k++){for(int p=0;p<10;p++)f[i+j+k*mid][p]=tmp[k][p];}
else for(int k=0;k<10;k++){for(int p=0;p<10;p++)f[i+j+k*mid][p]=(tmp[k][p]/2)*inv5;}
}
}
int main(){
#ifdef Stargazer
freopen("lx.cpp","r",stdin);
#endif
n=read();
for(int i=1;i<=n;i++){
int x=read();
chemx(mx,x);
f[x][0]++;
}
int lim=1;
while(lim<=mx)lim*=10;
fwt(f,lim,1);
for(int i=0;i<lim;i++)f[i]=ksm(f[i],n);
fwt(f,lim,-1);
for(int i=0;i<n;i++)cout<<f[i].val()<<'\n';
}