SPOJ Triple Sums(FFT+容斥原理)

# include <cstdio>
# include <cstring>
# include <cstdlib>
# include <iostream>
# include <vector>
# include <queue>
# include <stack>
# include <map>
# include <complex>
# include <set>
# include <cmath>
# include <algorithm>
using namespace std;
# define lowbit(x) ((x)&(-x))
const double pi=acos(-1.0);
# define eps 1e-8
# define MOD 1000000007
# define INF 1000000000
# define mem(a,b) memset(a,b,sizeof(a))
# define FOR(i,a,n) for(int i=a; i<=n; ++i)
# define FDR(i,a,n) for(int i=a; i>=n; --i)
# define bug puts("H");
# define lch p<<1,l,mid
# define rch p<<1|1,mid+1,r
# define mp make_pair
# define pb push_back
typedef pair<int,int> PII;
typedef vector<int> VI;
# pragma comment(linker, "/STACK:1024000000,1024000000")
typedef long long LL;
inline int Scan() {
    int x=0,f=1; char ch=getchar();
    while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘) f=-1; ch=getchar();}
    while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘; ch=getchar();}
    return x*f;
}
inline void Out(int a) {
    if(a<0) {putchar(‘-‘); a=-a;}
    if(a>=10) Out(a/10);
    putchar(a%10+‘0‘);
}
const int N=80005;
//Code begin....

typedef complex<double> cmx;
int c[N<<2], val[N<<2], a[N<<2], b[N<<2];
cmx x[N<<2], y[N<<2];

void change(cmx x[], int len) {
    int i, j, k;
    for(i=1, j=len>>1; i<len-1; ++i) {
        if(i<j) swap(x[i],x[j]);
        k=len>>1;
        while(j>=k) j-=k, k>>=1;
        if(j<k) j+=k;
    }
}
void fft(cmx x[], int len, int on) {
    change(x,len);
    for(int i=2; i<=len; i<<=1) {
        cmx wn(cos(-on*2*pi/i),sin(-on*2*pi/i));
        for(int j=0; j<len; j+=i) {
            cmx w(1,0);
            FOR(k,j,j+i/2-1) {
                cmx u=x[k], v=x[k+i/2]*w;
                x[k]=u+v; x[k+i/2]=u-v; w*=wn;
            }
        }
    }
    if(on==-1) FOR(i,0,len-1) x[i]/=len;
}
int main()
{
    int n, maxx=0;
    cmx three(3.0,0);
    scanf("%d",&n);
    FOR(i,1,n) scanf("%d",val+i), val[i]+=20000, maxx=max(maxx,val[i]);
    maxx*=3;
    FOR(i,1,n) ++a[val[i]], ++b[val[i]*2], ++c[val[i]*3];
    int len=1;
    while(len<maxx) len<<=1; //len要为2的幂次
    FOR(i,0,len-1) x[i]=cmx(a[i],0), y[i]=cmx(b[i],0);
    fft(x,len,1); fft(y,len,1); //将系数表达式转化为点值表达式
    FOR(i,0,len-1) x[i]=x[i]*x[i]*x[i]-x[i]*y[i]*three;
    fft(x,len,-1);
    FOR(i,0,len-1) a[i]=(int(x[i].real()+0.5)+2*c[i])/6;
    FOR(i,0,len-1) {
        if(!a[i]) continue;
        printf("%d : %d\n", i-3*20000,a[i]);
    }
    return 0;
}

时间: 2024-08-11 07:42:15

SPOJ Triple Sums(FFT+容斥原理)的相关文章

SPOJ - TSUM Triple Sums FFT+容斥

Triple Sums You're given a sequence s of N distinct integers.Consider all the possible sums of three integers from the sequence at three different indicies.For each obtainable sum output the number of different triples of indicies that generate it.Co

SPOJ 8372. Triple Sums

8372. Triple Sums Problem code: TSUM You're given a sequence s of N distinct integers.Consider all the possible sums of three integers from the sequence at three different indicies.For each obtainable sum output the number of different triples of ind

【bzoj3771】Triple FFT+容斥原理

题目描述 樵夫的每一把斧头都有一个价值,不同斧头的价值不同.总损失就是丢掉的斧头价值和. 他想对于每个可能的总损失,计算有几种可能的方案. 注意:如果水神拿走了两把斧头a和b,(a,b)和(b,a)视为一种方案.拿走三把斧头时,(a,b,c),(b,c,a),(c,a,b),(c,b,a),(b,a,c),(a,c,b)视为一种方案. 输入 第一行是整数N,表示有N把斧头. 接下来n行升序输入N个数字Ai,表示每把斧头的价值. 输出 若干行,按升序对于所有可能的总损失输出一行x y,x为损失值,

The Preliminary Contest for ICPC Asia Shanghai 2019 C Triple(FFT+暴力)

The Preliminary Contest for ICPC Asia Shanghai 2019 C Triple(FFT+暴力) 传送门:https://nanti.jisuanke.com/t/41400 题意: 给你三个数组a,b,c,要你求有多少个三元组(i,j,k),使得 \[ \begin{array}{l}{\left|A_{i}-B_{j}\right| \leq C_{k}, \text { and }} \\ {\left|B_{j}-C_{k}\right| \leq

SPOJ TSUM Triple Sums(FFT + 容斥)

题目 Source http://www.spoj.com/problems/TSUM/ Description You're given a sequence s of N distinct integers.Consider all the possible sums of three integers from the sequence at three different indicies.For each obtainable sum output the number of diff

【BZOJ3771】Triple 生成函数+FFT

[BZOJ3771]Triple Description 我们讲一个悲伤的故事. 从前有一个贫穷的樵夫在河边砍柴. 这时候河里出现了一个水神,夺过了他的斧头,说: “这把斧头,是不是你的?” 樵夫一看:“是啊是啊!” 水神把斧头扔在一边,又拿起一个东西问: “这把斧头,是不是你的?” 樵夫看不清楚,但又怕真的是自己的斧头,只好又答:“是啊是啊!” 水神又把手上的东西扔在一边,拿起第三个东西问: “这把斧头,是不是你的?” 樵夫还是看不清楚,但是他觉得再这样下去他就没法砍柴了. 于是他又一次答:“

BZOJ 3771 Triple 母函数+FFT

题目大意:给定n个物品,可以用一个/两个/三个不同的物品凑出不同的价值,求每种价值有多少种拼凑方案(顺序不同算一种) 首先搞出这n个物品的母函数a 将a的每项的平方求和得到多项式b 将a的每项的立方求和得到多项式c 那么如果不考虑顺序和重复 那么方案数就是a+b+c 现在考虑顺序和重复后 三个物品的方案数为(a^3-3*a*b+2*c)/6 两个物品的方案数为(a^2-b)/2 一个物品的方案数为a 故最终答案为(a^3-3*a*b+2*c)/6+(a^2-b)/2+a 用FFT搞一下就好了-

bzoj3771 Triple

3771: Triple Time Limit: 20 Sec  Memory Limit: 64 MB Submit: 313  Solved: 174 [Submit][Status][Discuss] Description 我们讲一个悲伤的故事. 从前有一个贫穷的樵夫在河边砍柴. 这时候河里出现了一个水神,夺过了他的斧头,说: "这把斧头,是不是你的?" 樵夫一看:"是啊是啊!" 水神把斧头扔在一边,又拿起一个东西问: "这把斧头,是不是你的?&q

BZOJ 3771: Triple [快速傅里叶变换 生成函数 容斥原理]

题意:n个物品,可以用1/2/3个不同的物品组成不同的价值,求每种价值有多少种方案(顺序不同算一种) 挖坑过会再写 生成函数系数为方案数,次数为价值 A(x) 选一个 B(x) A每项平方 选两个 C(x) A每项三次方 选三个 然后容斥原理算答案 注意计算的时候可以一直用点值,最后在变系数表示 #include <iostream> #include <cstdio> #include <string> #include <algorithm> #incl