题目

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 different triples of indicies that generate it.

Constraints:
N <= 40000, |si| <= 20000

Input

The first line of input contains a single integer N.
Each of the next N lines contain an element of s.

Output

Print the solution for each possible sum in the following format:
sum_value : number_of_triples

Smaller sum values should be printed first.

Sample Input

5
-1
2
3
0
5

Sample Output

1 : 1
2 : 1
4 : 2
5 : 1
6 : 1
7 : 2
8 : 1
10 : 1

分析

题目大概说给n个数,从中选出三个数求和,问能到的各个和分别有几种取法能够得到?

这题很容易。。因为刚做过HDU4609。。
就是根据初始的序列构造出三个一样的多项式,指数表示数字,系数表示该数字出现次数。
然后三个多项式的乘积相当于表示有顺序有放回地取数字的结果。这个用FFT求。

不过这不是组合,可以用容斥原理去掉那些取法重复的。
即减去3种两个取同一边的情况,这个也用FFT求;然后加上三个都取同一边的情况,for一遍即可求;最后除以3的阶乘。

注意到时间好像比较紧,所以我做了些处理,比如三个多项式相乘直接三个点值相乘、避免重复的DFT过程。。
。。然后没想到居然暂时列第二,与第一同时间:

代码

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
#define MAXN 131072
const double PI=acos(-1.0); struct Complex{
double real,imag;
Complex(double _real=0,double _imag=0):real(_real),imag(_imag){}
Complex operator+(const Complex &cp) const{
return Complex(real+cp.real,imag+cp.imag);
}
Complex operator-(const Complex &cp) const{
return Complex(real-cp.real,imag-cp.imag);
}
Complex operator*(const Complex &cp) const{
return Complex(real*cp.real-imag*cp.imag,real*cp.imag+cp.real*imag);
}
void setValue(double _real=0,double _imag=0){
real=_real; imag=_imag;
}
}; int len;
Complex wn[MAXN+1],wn_anti[MAXN+1]; void FFT(Complex y[],int op){
for(int i=1,j=len>>1,k; i<len-1; ++i){
if(i<j) swap(y[i],y[j]);
k=len>>1;
while(j>=k){
j-=k;
k>>=1;
}
if(j<k) j+=k;
}
for(int h=2; h<=len; h<<=1){
Complex Wn=(op==1?wn[h]:wn_anti[h]);
for(int i=0; i<len; i+=h){
Complex W(1,0);
for(int j=i; j<i+(h>>1); ++j){
Complex u=y[j],t=W*y[j+(h>>1)];
y[j]=u+t;
y[j+(h>>1)]=u-t;
W=W*Wn;
}
}
}
if(op==-1){
for(int i=0; i<len; ++i) y[i].real/=len;
}
} Complex A[MAXN],B[MAXN];
double ans[MAXN];
int s[40100],cnt[80100]; int main(){
for(int i=0; i<=MAXN; ++i){
wn[i].setValue(cos(2.0*PI/i),sin(2.0*PI/i));
wn_anti[i].setValue(wn[i].real,-wn[i].imag);
} int n;
scanf("%d",&n);
for(int i=0; i<n; ++i){
scanf("%d",&s[i]);
s[i]+=20000;
++cnt[s[i]];
} len=MAXN; for(int i=0; i<=40000; ++i){
B[i].setValue(cnt[i]);
}
FFT(B,1);
for(int i=0; i<MAXN; ++i){
A[i]=B[i]*B[i]*B[i];
}
FFT(A,-1);
for(int i=0; i<MAXN; ++i){
ans[i]=A[i].real;
} memset(cnt,0,sizeof(cnt));
for(int i=0; i<n; ++i){
++cnt[s[i]+s[i]];
}
for(int i=0; i<=80000; ++i){
A[i].setValue(cnt[i]);
}
for(int i=80001; i<MAXN; ++i){
A[i].setValue(0);
}
FFT(A,1);
for(int i=0; i<MAXN; ++i){
A[i]=A[i]*B[i];
}
FFT(A,-1);
for(int i=0; i<MAXN; ++i){
ans[i]-=3*A[i].real;
} for(int i=0; i<n; ++i){
++ans[s[i]+s[i]+s[i]];
} for(int i=0; i<MAXN; ++i){
long long tmp=(long long)(ans[i]/6.0+0.5);
if(tmp){
printf("%d : %lld\n",i-60000,tmp);
}
}
return 0;
}

SPOJ TSUM Triple Sums(FFT + 容斥)的更多相关文章

  1. spoj TSUM - Triple Sums fft+容斥

    题目链接 首先忽略 i < j < k这个条件.那么我们构造多项式$$A(x) = \sum_{1现在我们考虑容斥:1. $ (\sum_{}x)^3 = \sum_{}x^3 + 3\s ...

  2. BZOJ.3771.Triple(母函数 FFT 容斥)

    题目链接 \(Description\) 有\(n\)个物品(斧头),每个物品价值不同且只有一件,问取出一件.两件.三件物品,所有可能得到的价值和及其方案数.\((a,b),(b,a)\)算作一种方案 ...

  3. 【BZOJ 3771】 3771: Triple (FFT+容斥)

    3771: Triple Time Limit: 20 Sec  Memory Limit: 64 MBSubmit: 547  Solved: 307 Description 我们讲一个悲伤的故事. ...

  4. BZOJ 3771: Triple(FFT+容斥)

    题面 Description 我们讲一个悲伤的故事. 从前有一个贫穷的樵夫在河边砍柴. 这时候河里出现了一个水神,夺过了他的斧头,说: "这把斧头,是不是你的?" 樵夫一看:&qu ...

  5. HDU 4609 3-idiots FFT+容斥

    一点吐槽:我看网上很多分析,都是在分析这个题的时候,讲了半天的FFT,其实我感觉更多的把FFT当工具用就好了 分析:这个题如果数据小,统计两个相加为 x 的个数这一步骤(这个步骤其实就是求卷积啊),完 ...

  6. Spoj 8372 Triple Sums

    题意:给你n个数字,对于任意s,s满足\(s=u_i+u_j+u_k,i<j<k\),要求出所有的s和对应满足条件的i,j,k的方案数 Solution: 构造一个函数:\(A(x)=\s ...

  7. 【XSY2753】Lcm 分治 FWT FFT 容斥

    题目描述 给你\(n,k\),要你选一些互不相同的正整数,满足这些数的\(lcm\)为\(n\),且这些数的和为\(k\)的倍数. 求选择的方案数.对\(232792561\)取模. \(n\leq ...

  8. SPOJ - TSUM 母函数+FFT+容斥

    题意:n个数,任取三个加起来,问每个可能的结果的方案数. 题解:构造母函数ABC,比如现在有 1 2 3 三个数.则 其中B表示同一个数加两次,C表示用三次.然后考虑去重. A^3表示可重复地拿三个. ...

  9. SPOJ:Triple Sums(母函数+FFT)

    You're given a sequence s of N distinct integers.Consider all the possible sums of three integers fr ...

随机推荐

  1. ASCII 非打印字符

    项目出了问题,因为AscII非打印字符的原因,后来找了一下啊ASCII的非打印字符,总共有31个,然后我们直接全部替换成问号了. 解决方式为先找到非打印字符,这是我从网上找的非打印字符表: 进制 十六 ...

  2. hdu 1005

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1005 思路:找规律题 #include<stdio.h> main() { ]; int ...

  3. python中获取当前日期在当月是第几天

  4. JAVA一些常用的时间操作

    项目中经常有对时间进行处理的需求,下面是一些常用的操作整理,方便以后再次使用以及做相关复习. 1.字符串转换为日期 /** * 字符串转换为日期 * @param dateStr 需要转换的日期 * ...

  5. jQuery函数attr()和prop()的区别

    在jQuery中,attr()函数和prop()函数都用于设置或获取指定的属性,它们的参数和用法也几乎完全相同. 但不得不说的是,这两个函数的用处却并不相同.下面我们来详细介绍这两个函数之间的区别. ...

  6. C# SMTP邮件发送 分类: C# 2014-07-13 19:10 333人阅读 评论(1) 收藏

    邮件发送在网站应用程序中经常会用到,包括您现在看到的博客,在添加评论后,系统会自动发送邮件通知到我邮箱的,把系统发送邮件的功能整理了下,做了一个客户端Demo,希望对有需要的童鞋有所帮助: 核心代码: ...

  7. .NET yield

    .Net Yield 其实比较简单,手动yield,一学就会. public static class GalaxyClass { public static void ShowGalaxies() ...

  8. Oracle优化的几个简单步骤

    数据库优化的讨论可以说是一个永恒的主题.资深的Oracle优化人员通常会要求提出性能问题的人对数据库做一个statspack,贴出数据库配置等等.还有的人认为要抓出执行最慢的语句来进行优化.但实际情况 ...

  9. PathFinding.js 寻路类神器

    最近有打算写个迷宫玩玩,无意中发下了这个库,很强大!又是开源在github的,并且有一个相当酷的demo.这个库不仅支持浏览器端的运行,而且可以运行在node.js上.怎么用到服务器上这里就不涉及了, ...

  10. DateTime还是DateTimeOffset?Now还是UtcNow?

    (此文章同时发表在本人微信公众号"dotNET每日精华文章",欢迎右边二维码来关注.) 题记:新年第一篇文章,就来谈谈关于时间的简单技术问题:该用DateTime还是DateTim ...