CF1103E Radix sum
其他题解怎么感觉都是在硬凑,这里介绍一下
这题求的就是
由于每一位独立,所以我们对每一位单独做 DFT 即可,在单位根存在时,这样的复杂度是
由于
但这样是不对的,由于
值得注意的是,我们大多数时候并不需要证明其在
还有一个问题是,
关于分圆多项式怎么算,我们有
void init(){
T[0]=1;
for(auto i:d[k]){//d 为 k 的所有 square-free 因子
if(mu[k/i]==1) for(int j=phi[k];j>=i;j--) T[j]-=T[j-i];
else if(mu[k/i]==-1) for(int j=i;j<=phi[k];j++) T[j]+=T[j-i];
}
}
时间复杂度
#include<iostream>
#include<string>
using std::cin;
using std::cout;
#define int unsigned long long
int const iv5=14757395258967641293ull;
int n,k,m,pw[10],lim,iv;
int pow(int x,int y){
int res=1;
while(y){
if(y&1) res*=x;
x*=x,y>>=1;
}
return res;
}
struct node{
int a[11];
node():a(){}
int operator [](int x)const{return a[x];}
int& operator [](int x){return a[x];}
void operator +=(node const &x){for(int i=0;i<k;i++) a[i]+=x[i];}
void operator *=(int y){for(int i=0;i<k;i++) a[i]*=y;}
friend node operator *(node const &x,node const &y){
static int a[30];
node ans;
for(int i=0;i<k+k;i++) a[i]=0;
for(int i=0;i<k;i++) for(int j=0;j<k;j++) a[i+j]+=x[i]*y[j];
for(int i=0;i<k;i++) ans[i]=a[i]+a[i+k];
return ans;
}
friend node operator +(node const &x,node const &y){
node ans;
for(int i=0;i<k;i++) ans[i]=x[i]+y[i];
return ans;
}
node apply(int x)const{
x%=k;
node ans;
for(int i=0;i<k;i++) ans[(i+x)%k]=a[i];
return ans;
}
node iapply(int x)const{
x%=k;
x=(k-x)%k;
node ans;
for(int i=0;i<k;i++) ans[(i+x)%k]=a[i];
return ans;
}
}T,ct[100010];
node pow(node x,int y){
node res;
res[0]=1;
while(y){
if(y&1) res=res*x;
x=x*x,y>>=1;
}
return res;
}
void dwt(node *c){
for(int i=0;i<m;i++)
for(int a=0;a<lim;a+=pw[i+1])
for(int b=0;b<pw[i];b++){
static node x[11],y[11];
for(int j=0;j<k;j++) x[j]=c[a+b+j*pw[i]],y[j]=node();
for(int j=0;j<k;j++) for(int u=0;u<k;u++) y[j]+=x[u].apply(j*u);
for(int j=0;j<k;j++) c[a+b+j*pw[i]]=y[j];
}
}
void idwt(node *c){
for(int i=0;i<m;i++)
for(int a=0;a<lim;a+=pw[i+1])
for(int b=0;b<pw[i];b++){
static node x[11],y[11];
for(int j=0;j<k;j++) x[j]=c[a+b+j*pw[i]],y[j]=node();
for(int j=0;j<k;j++) for(int u=0;u<k;u++) y[j]+=x[u].iapply(j*u);
for(int j=0;j<k;j++) c[a+b+j*pw[i]]=y[j];
}
}
void init(){
T[0]=1,T[1]=-1ull,T[2]=1,T[3]=-1ull,T[4]=1;
}
int deal(node x){
int n=4;
for(int i=k-1;i>=n;i--){
int u=x[i];
for(int j=1;j<=n;j++) x[i-j]-=u*T[n-j];
}
int u=x[0];
u*=iv;
u>>=m;
return u%(1ull<<58);
}
signed main(){
std::ios::sync_with_stdio(false),cin.tie(nullptr);
k=10,m=5;
pw[0]=1;
for(int i=1;i<=m;i++) pw[i]=pw[i-1]*k;
lim=pw[m],iv=pow(iv5,m);
cin>>n;
for(int i=1;i<=n;i++){
int x;
cin>>x;
++ct[x][0];
}
dwt(ct);
for(int i=0;i<lim;i++) ct[i]=pow(ct[i],n);
idwt(ct);
init();
for(int i=0;i<n;i++) cout<<deal(ct[i])<<'\n';
return 0;
}