HDU 1402 http://acm.hdu.edu.cn/showproblem.php?pid=1402
#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
#include <cmath>
using namespace std;
const int maxn=150020;
const double PI=acos(-1.0);
struct Com{//复数,重载+,-,* complex
double a,b;
Com(double aa=0,double bb=0){a=aa;b=bb;}
Com operator +(const Com &e){return Com(a+e.a,b+e.b);}
Com operator -(const Com &e){return Com(a-e.a,b-e.b);}
Com operator *(const Com &e){return Com(a*e.a-b*e.b,a*e.b+b*e.a);}
};
void change(Com y[],int len){
int i,j,k;
for(i=1,j=len/2;i<len-1;i++){
if(i<j) swap(y[i],y[j]);
k=len/2;
while(j>=k){
j-=k;
k/=2;
}
if(j<k)j+=k;
}
}
//FFT快速傅里叶变换的模板,用以将多项式系数转换成单位根(??应该是),这样得到的两个序列逐个相乘到得就是系数
//序列的卷积,即两个多项式乘积后的系数值
void FFT(Com y[],int len,int on){
change(y,len);
for(int h=2;h<=len;h<<=1){
Com wn(cos(-on*2*PI/h),sin(-on*2*PI/h));
for(int j=0;j<len;j+=h){
Com w(1,0);
for(int k=j;k<j+h/2;k++){
Com u=y[k];
Com t=w*y[k+h/2];
y[k]=u+t;
y[k+h/2]=u-t;
w=w*wn;
}
}
}
if(on==-1)
for(int i=0;i<len;i++)
y[i].a/=len;
}
int n;
char s1[maxn/3];
char s2[maxn/3];
int l1,l2,l;
int ans[maxn];
Com x1[maxn],x2[maxn];
int main(){
while(scanf("%s%s",s1,s2)!=EOF){
l1=strlen(s1);
l2=strlen(s2);
l=1;
while(l<=l1+l2) l<<=1; // 必须 l>l1+l2 && l>2^.. !!!
for(int i=l1-1;i>=0;i--) x1[l1-i-1]=Com(s1[i]-'0',0);
for(int i=l1;i<l;i++) x1[i]=Com(0,0);
for(int i=l2-1;i>=0;i--) x2[l2-i-1]=Com(s2[i]-'0',0);
for(int i=l2;i<l;i++) x2[i]=Com(0,0);
FFT(x1,l,1);FFT(x2,l,1);
for(int i=0;i<l;i++)
x1[i]=x1[i]*x2[i];
FFT(x1,l,-1);
//memset(ans,0,sizeof(ans));
for(int i=0;i<l;i++){
if(i==0) ans[i]=(x1[i].a+0.5);
else{
ans[i]=ans[i-1]/10+(x1[i].a+0.5);
ans[i-1]%=10;
}
}
int k=l-1;
while(ans[k]==0&&k>0) k--;
for(int i=k;i>=0;i--) printf("%d",ans[i]);
puts("");
}
}
/*
A*B
Sample Input
1
2
1000
2
Sample Output
2
2000
*/
HDU 4609 http://acm.hdu.edu.cn/showproblem.php?pid=4609
#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
#include <cmath>
using namespace std;
typedef long long ll;
const int maxn=300020;
const double PI=acos(-1.0);
struct Com{//复数,重载+,-,* complex
double a,b;
Com(double aa=0,double bb=0){a=aa;b=bb;}
Com operator +(const Com &e){return Com(a+e.a,b+e.b);}
Com operator -(const Com &e){return Com(a-e.a,b-e.b);}
Com operator *(const Com &e){return Com(a*e.a-b*e.b,a*e.b+b*e.a);}
};
void change(Com y[],int len){
int i,j,k;
for(i=1,j=len/2;i<len-1;i++){
if(i<j) swap(y[i],y[j]);
k=len/2;
while(j>=k){
j-=k;
k/=2;
}
if(j<k)j+=k;
}
}
//FFT快速傅里叶变换的模板,用以将多项式系数转换成单位根(??应该是),这样得到的两个序列逐个相乘到得就是系数
//序列的卷积,即两个多项式乘积后的系数值
void FFT(Com y[],int len,int on){
change(y,len);
for(int h=2;h<=len;h<<=1){
Com wn(cos(-on*2*PI/h),sin(-on*2*PI/h));
for(int j=0;j<len;j+=h){
Com w(1,0);
for(int k=j;k<j+h/2;k++){
Com u=y[k];
Com t=w*y[k+h/2];
y[k]=u+t;
y[k+h/2]=u-t;
w=w*wn;
}
}
}
if(on==-1)
for(int i=0;i<len;i++)
y[i].a/=len;
}
int cnt[maxn];
int num[maxn];
Com x1[maxn];
Com x2[maxn];
ll sum[maxn];
int main()
{
int t;
scanf("%d",&t);
while(t--){
int l=1,m;
scanf("%d",&m);
int n=0;
memset(cnt,0,sizeof(cnt));
for(int i=0;i<m;i++){scanf("%d",&num[i]);cnt[num[i]]++;n=max(n,num[i]);}
while(l<=(n+n)) l<<=1;
for(int i=0;i<l;i++) x1[i]=x2[i]=Com(cnt[i],0);
FFT(x1,l,1);FFT(x2,l,1);
for(int i=0;i<l;i++) x1[i]=x1[i]*x2[i];
FFT(x1,l,-1);
for(int i=0;i<l;i++) sum[i]=(ll)(x1[i].a+0.5);
for(int i=0;i<m;i++) sum[num[i]+num[i]]--;
for(int i=0;i<l;i++) sum[i]/=2;
for(int i=1;i<l;i++) sum[i]+=sum[i-1];
ll all=(ll)m*((ll)m-1)*((ll)m-2)/6;
ll ans=all;
for(int i=0;i<m;i++) ans-=sum[num[i]];
printf("%.7f\n",(double)(ans)/all);
}
}