# BZOJ 3771 生成函数，FFT

## Description

“这把斧头，是不是你的？”

“这把斧头，是不是你的？”

“这把斧头，是不是你的？”

“你看看你现在的样子，真是丑陋！”

4
4
5
6
7

## Sample Output

4 1
5 1
6 1
7 1
9 1
10 1
11 2
12 1
13 1
15 1
16 1
17 1
18 1

11有两种方案是4+7和5+6，其他损失值都有唯一方案，例如4=4,5=5,10=4+6,18=5+6+7.

## HINT

#include <bits/stdc++.h>
using namespace std;
const int maxn = 300000;
typedef long long LL;
const double PI = acos(-1.0);
typedef complex <double> Complex;

void rader(Complex *y, int len) {
for(int i = 1, j = len / 2; i < len - 1; i++) {
if(i < j) swap(y[i], y[j]);
int k = len / 2;
while(j >= k) {j -= k; k /= 2;}
if(j < k) j += k;
}
}
void fft(Complex *y, int len, int op) {
for(int h = 2; h <= len; h <<= 1) {
double ang = op * 2 * PI / h;
Complex wn(cos(ang), sin(ang));
for(int j = 0; j < len; j += h) {
Complex w(1, 0);
for(int k = j; k < j + h / 2; k++) {
Complex u = y[k];
Complex t = w * y[k + h / 2];
y[k] = u + t;
y[k + h / 2] = u - t;
w = w * wn;
}
}
}
if(op == -1) for(int i = 0; i < len; i++) y[i] /= len;
}

Complex a[maxn],b[maxn],c[maxn];
int n, len, x, m, mx;

int main()
{
scanf("%d", &n);
for(int i=0; i<n; i++){
scanf("%d", &x);
a[x]+=(1),b[2*x]+=(1),c[3*x]+=(1);
mx = max(mx, 3*x);
}
mx++;
len = 1;
while(len < mx*2){
len <<= 1;
}
m = len+1;
fft(a, len, 1);
fft(b, len, 1);
fft(c, len, 1);
Complex t2=(2),t3=(3),t6=(6);
for (int i=0;i<len;i++)
a[i]=(a[i]*a[i]*a[i]-t3*a[i]*b[i]+t2*c[i])/t6+(a[i]*a[i]-b[i])/t2+a[i];
fft(a, len, -1);
for(int i=1; i<m; i++){
LL num = (LL)(a[i].real()+0.5);
if(num!=0) printf("%d %lld\n", i,num);
}
return 0;
}


posted @ 2017-08-22 10:06  zxycoder  阅读(207)  评论(0编辑  收藏  举报