2019 上海icpc网络赛 C FFT+暴力

匿名 (未验证) 提交于 2019-12-03 00:07:01

https://nanti.jisuanke.com/t/41400

对于大的情况,我们依次对a与b,a与c,c与b去卷积,然后答案就是$n^3$,卷积后减去不合法的情况

但是由于值域每次都是1e5,单组复杂度每次都是$1e5*log1e5$且常数很大

但是我们发现,只有20组n>1000

因此,对于小范围数据,我们直接使用$1000*1000$的暴力

#include<bits/stdc++.h> #define ll long long #define rep(ii,a,b) for(int ii=a;ii<=b;++ii) #define per(ii,a,b) for(int ii=b;ii>=a;--ii) using namespace std;//head const int maxn=4e5+10,maxm=2e6+10; const ll INF=0x3f3f3f3f,mod=1e9+7; int casn,n,m,k,kase=1,l,r; namespace fastio{//@支持读取整数,字符串,输出整数@ bool isdigit(char c){return c>=48&&c<=57;} const int maxsz=1e7; class fast_iostream{public:   char ch=get_char();   bool endf=1,flag;   char get_char(){     static char buffer[maxsz],*a=buffer,*b=buffer;     return b==a&&(b=(a=buffer)+fread(buffer,1,maxsz, stdin),b==a)?EOF:*a++;   }   template<typename type>bool get_int(type& tmp){     flag=tmp=0;     while(!isdigit(ch)&&ch!=EOF){flag=ch=='-';ch=get_char();};     if(ch==EOF)return endf=0;     do{tmp=ch-48+tmp*10;}while(isdigit(ch=get_char()));     if(flag)tmp=-tmp;     return 1;   }   int get_str(char* str){     char* tmp=str;     while(ch=='\r'||ch=='\n'||ch==' ')ch=get_char();     if(ch==EOF)return(endf=0),*tmp=0;     do{*(tmp++)=ch;ch=get_char();}while(ch!='\r'&&ch!='\n'&&ch!=' '&&ch!=EOF);     *(tmp++)=0;     return(int)(tmp-str-1);   }   fast_iostream& operator>>(char* tmp){get_str(tmp);return *this;}   template<typename type>fast_iostream& operator>>(type& tmp){get_int(tmp);return *this;}   operator bool() const {return endf;} }; }fastio::fast_iostream io;  const double pi=acos(-1.0); struct cp{double x,y;}; cp operator*(cp a,cp b){return {a.x*b.x-a.y*b.y,a.x*b.y+a.y*b.x};} cp operator+(cp a,cp b){return {a.x+b.x,a.y+b.y};} cp operator-(cp a,cp b){return {a.x-b.x,a.y-b.y};} class fourier{public:   int rev[maxn],len,pw;   void init(int n){     len=1,pw=0;     while(len<=n) len<<=1,pw++;     rep(i,0,len-1) rev[i]=0;     rep(i,0,len-1) rev[i]=(rev[i>>1]>>1)|((i&1)<<(pw-1));   }   void transform(cp*a,int flag){     rep(i,0,len-1) if(i<rev[i]) swap(a[i],a[rev[i]]);     for(int mid=1;mid<len;mid<<=1){       cp wn={cos(pi/mid),flag*sin(pi/mid)};       for(int r=mid<<1,j=0;j<len;j+=r){         cp t={1,0};         for(int k=0;k<mid;k++,t=t*wn){           cp x=a[j+k],y=t*a[mid+j+k];           a[j+k]=x+y,a[j+k+mid]=x-y;         }       }     }     if(flag==-1) rep(i,0,len) a[i].x/=len;   } }fft; int a[maxn],b[maxn],c[maxn]; cp cnta[maxn],cntb[maxn],cntc[maxn]; cp resa[maxn],resb[maxn],resc[maxn]; ll suma[maxn],sumb[maxn],sumc[maxn]; #define cin io int main(){   cin>>casn;   while(kase<=casn){     cin>>n;     fft.init(1e5+1e5+2);     if(n<=1000){       rep(i,1,n)cin>>a[i];       rep(i,1,n)cin>>b[i];       rep(i,1,n)cin>>c[i];       ll ans=1ll*n*n*n;       sort(c+1,c+1+n);       sort(b+1,b+1+n);       sort(a+1,a+1+n);       rep(i,1,c[n]) suma[i]=0;       rep(i,1,n)rep(j,1,n) ++suma[a[i]+b[j]];       rep(i,1,c[n])suma[i]+=suma[i-1];       rep(i,1,n) ans-=suma[c[i]-1];       rep(i,1,b[n]) suma[i]=0;       rep(i,1,n)rep(j,1,n) ++suma[a[i]+c[j]];       rep(i,1,b[n])suma[i]+=suma[i-1];       rep(i,1,n) ans-=suma[b[i]-1];       rep(i,1,a[n]) suma[i]=0;       rep(i,1,n)rep(j,1,n) ++suma[c[i]+b[j]];       rep(i,1,a[n])suma[i]+=suma[i-1];       rep(i,1,n) ans-=suma[a[i]-1];       printf("Case #%d: %lld\n",kase++,ans);       continue;      }     rep(i,1,n) {       cin>>a[i];       cnta[a[i]].x++;     }     rep(i,1,n) {       cin>>b[i];       cntb[b[i]].x++;     }     rep(i,1,n) {       cin>>c[i];       cntc[c[i]].x++;     }     fft.transform(cnta,1);fft.transform(cntb,1);fft.transform(cntc,1);     rep(i,0,fft.len-1){       resa[i]=cntb[i]*cntc[i];       resb[i]=cnta[i]*cntc[i];       resc[i]=cntb[i]*cnta[i];     }     fft.transform(resa,-1);fft.transform(resb,-1);fft.transform(resc,-1);     rep(i,1,fft.len-1){       suma[i]=suma[i-1]+(ll)(resa[i].x+0.5);       sumb[i]=sumb[i-1]+(ll)(resb[i].x+0.5);       sumc[i]=sumc[i-1]+(ll)(resc[i].x+0.5);     }     ll ans=n*1ll*n*n;     rep(i,1,n){       ans-=suma[a[i]-1]+sumb[b[i]-1]+sumc[c[i]-1];     }     printf("Case #%d: %lld\n",kase++,ans);     rep(i,0,fft.len){       cnta[i]=cntb[i]=cntc[i]=(cp){0,0};     }   } } 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!