(2016北京集训十)【xsy1529】小Q与进位制 - 分治FFT

时间:2023-03-09 19:33:46
(2016北京集训十)【xsy1529】小Q与进位制 - 分治FFT

(2016北京集训十)【xsy1529】小Q与进位制 - 分治FFT

题意很简单,就是求这个数。。。

其实场上我想出了分治fft的正解。。。然而不会打。。。然后打了个暴力fft挂了。。。

没啥好讲的,这题很恶心,卡常卡精度还爆int,要各种优化,有些dalao写的很复杂我都没看懂。。。我写的是每三位拆分然后再合并

代码:

 //强烈谴责卡常数而需要大量优化
//upd:还卡精度。。。
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<queue>
#define inf 2147483647
#define eps 1e-9
using namespace std;
typedef long long ll;
const double pi=acos(-);
struct complex{
double a,b;
complex(double _a=,double _b=){
a=_a;
b=_b;
}
friend complex operator +(complex x,complex y){return complex(x.a+y.a,x.b+y.b);}
friend complex operator -(complex x,complex y){return complex(x.a-y.a,x.b-y.b);}
friend complex operator *(complex x,complex y){return complex(x.a*y.a-x.b*y.b,x.a*y.b+x.b*y.a);}
friend complex operator *(complex x,double y){return complex(x.a*y,x.b*y);}
friend complex operator /(complex x,double y){return complex(x.a/y,x.b/y);}
};
int n,tot=,bit,bitnum,rev[],tmp[],A[],B[],bs[],a[];
char out[];
void fft(complex *s,int op){
for(int i=;i<bit;i++)if(i<rev[i])swap(s[i],s[rev[i]]);
for(int i=;i<bit;i<<=){
complex w(cos(pi/i),op*sin(pi/i));
for(int p=i<<,j=;j<bit;j+=p){
complex wk(,);
for(int k=j;k<i+j;k++,wk=wk*w){
complex x=s[k],y=wk*s[k+i];
s[k]=x+y;
s[k+i]=x-y;
}
}
}
if(op==-){
for(int i=;i<=bit;i++){
s[i]=s[i]/(double)bit;
}
}
}
void mul(int a[],int b[],int c[],int n,int m){
static complex s1[],s2[];
for(bitnum=,bit=;bit<=m+n;bit<<=)bitnum++;
for(int i=;i<bit;i++){
rev[i]=(rev[i>>]>>)|((i&)<<(bitnum-));
}
for(int i=;i<n;i++)s1[i].a=a[i],s1[i].b=;
for(int i=;i<m;i++)s2[i].a=b[i],s2[i].b=;
for(int i=n;i<bit;i++)s1[i].a=s1[i].b=;
for(int i=m;i<bit;i++)s2[i].a=s2[i].b=;
fft(s1,);
fft(s2,);
for(int i=;i<bit;i++)s1[i]=s1[i]*s2[i];
fft(s1,-);
ll p=;
for(int i=;i<m+n||p;i++){
p+=(ll)(s1[i].a+0.5);
c[i]=p%;
p/=;
}
}
void add(int a[],int b[],int n){
int p=;
for(int i=;i<n||p;i++){
p+=a[i]+b[i];
a[i]=p%;
p/=;
}
}
void cdq(int l,int r,int A[],int B[]){
if(l==r){
A[]=bs[l]%;
A[]=bs[l]/%;
A[]=bs[l]/;
B[]=a[l]%;
B[]=a[l]/%;
B[]=a[l]/;
return;
}
int mid=(l+r)/,ll=(mid-l+)*,rr=(r-mid+)*;
cdq(l,mid,A,B);
cdq(mid+,r,A+ll,B+ll);
for(int i=;i<ll;i++)tmp[i]=B[i];
mul(A,B+ll,B,ll,rr);
add(B,tmp,ll);
mul(A,A+ll,A,ll,rr);
}
void delete_zero(char s[]){
int i,j;
tot--;
for(i=tot;i>=;i--){
if(s[i]!='')break;
}
s[i+]=;
j=i;
for(i=;i<j;i++,j--)swap(s[i],s[j]);
}
int main(){
scanf("%d",&n);
for(int i=;i<=n;i++){
scanf("%d",&bs[i]);
}
for(int i=;i<=n;i++){
scanf("%d",&a[i]);
}
cdq(,n,A,B);
//for(int i=0;i<=n<<1;i++)printf("%d ",B[i]);
for(int i=;i<=n<<;i++){
for(int j=;j<;j++){
out[tot++]=B[i]%+'';
B[i]/=;
}
}
//delete_zero(out);
int i,j;
tot--;
for(i=tot;i>=;i--){
if(out[i]!='')break;
}
out[i+]=;
j=i;
for(i=;i<j;i++,j--)swap(out[i],out[j]);
puts(out);
return ;
}