hdu 4609
来源:互联网 发布:java并发编程应用在哪 编辑:程序博客网 时间:2024/05/29 12:18
题目描述:
1e5个长度1e5以内的棍子,随便挑出3根不同的(长度可以相同)的棍,问组成三角形的概率
题解:
主要分两块:(1)fft可以快速算出两个棍子和是多少和几个的情况.通过减去单个的和/2后续处理可以得到.(2)有了a+b,并没有a-b.于是思维转换,不对a+b挑c,而是枚举c找a+b.并且定义枚举的c是最大的(这里的最大,如果一样,则标号最大,只是为了不统计重复).这样巧妙地把a-b
重点:
关键是第二个思路的转换
代码:
#include <iostream>#include <cstdio>#include <cstring>#include <string>#include <cmath>#include <ctype.h>#include <limits.h>#include <cstdlib>#include <algorithm>#include <vector>#include <queue>#include <map>#include <stack>#include <set>#include <bitset>#define CLR(a) memset(a, 0, sizeof(a))#define REP(i, a, b) for(ll i = a;i < b;i++)#define REP_D(i, a, b) for(ll i = a;i <= b;i++)typedef long long ll;using namespace std;const double PI = acos(-1.0);const ll maxn = 5e5 + 100;ll num[maxn], a[maxn];ll sum[maxn];ll n, len, num_n;//复数结构体struct Complex{ double x,y;//实部和虚部 x+yi Complex(double _x = 0.0,double _y = 0.0) { x = _x; y = _y; } Complex operator -(const Complex &b)const { return Complex(x-b.x,y-b.y); } Complex operator +(const Complex &b)const { return Complex(x+b.x,y+b.y); } Complex operator *(const Complex &b)const { return Complex(x*b.x-y*b.y,x*b.y+y*b.x); }};Complex x1[maxn],x2[maxn];/** 进行FFT和IFFT前的反转变换。* 位置i和 (i二进制反转后位置)互换* len必须去2的幂*/void change(Complex y[],ll len){ ll i,j,k; for(i = 1, j = len/2; i <len-1; i++) { if(i < j)swap(y[i],y[j]);//交换互为小标反转的元素,i<j保证交换一次//i做正常的+1,j左反转类型的+1,始终保持i和j是反转的 k = len/2; while(j >= k) { j -= k; k /= 2; } if(j < k)j += k; }}/** 做FFT* len必须为2^k形式,* on==1时是DFT,on==-1时是IDFT*/void fft(Complex y[],ll len,ll on){ change(y,len); for(ll h = 2; h <= len; h <<= 1) { Complex wn(cos(-on*2*PI/h),sin(-on*2*PI/h)); for(ll j = 0; j < len; j+=h) { Complex w(1,0); for(ll 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(on == -1) for(ll i = 0; i < len; i++) y[i].x /= len;}void doFFT(ll a[], ll &len){ ll len1 = 1; while(len1 < 2*len) { len1*=2; } for(ll i=0;i<len;i++) { x1[i] = Complex(a[i], 0); } for(ll i=len;i<len1;i++) { x1[i] = Complex(0, 0); } fft(x1, len1, 1); for(ll i=0;i < len1;i++) { x1[i] = x1[i]*x1[i]; } fft(x1, len1, -1); len=len1; for(ll i=0;i < len;i++) { a[i] = (ll)(x1[i].x+0.5); }}ll select(ll x){ if(x==0) return 0; if(x==1) return 0; return x*(x-1)/2;}void solve(){ sort(a, a+n); len = a[n-1]+1; num_n = len; CLR(num); REP(i, 0, n) { num[a[i]]++; } //fft doFFT(num, num_n); REP(i, 0, n) { num[a[i]+a[i]]--; } REP(i, 0, num_n) {// if(num[i]%2!=0)// printf("dfasdfasd"); num[i] /= 2; } //printf("%I64d\n", num_n); sum[0]=0; REP(i, 1, num_n) { sum[i]=sum[i-1]+num[i]; } ll ans=0; REP(i, 0, n) { ans += (sum[num_n-1] - sum[a[i]]); ans -= (n-1); ans -= select(n-i-1); ans -= (n-i-1)*i; } ll tot = n*(n-1)*(n-2)/6; double res = ans*1.0/(double)tot; printf("%.7f\n", res);}int main(){ //freopen("3Cin.txt", "r", stdin); //freopen("3Cout.txt", "w", stdout); ll t; scanf("%I64d", &t); while(t--) { scanf("%I64d", &n); REP(i, 0, n) { scanf("%I64d", &a[i]); } solve(); } return 0;}
0 0
- HDU 4609
- hdu 4609
- HDU 4609 快速傅里叶变换
- hdu 4609 3-idiots
- 【FFT】HDU 4609
- Hdu 4609 FFT
- HDU 4609 FFT
- hdu 4609 3-idiots
- HDU 4609 3-idiots
- HDU 4609 3-idiots
- hdu 4609 3-idiots
- HDU-4609-FFT
- HDU 4609 快速傅里叶变换
- HDU 4609 3-idiots
- hdu
- hdu
- HDU
- hdu ()
- Java中的泛型
- [iOS]深入浅出 iOS 之多线程 NSThread
- 大公司最喜欢问的Java集合类面试题
- 查找(三)哈希表查找
- System.Threading.Timer 定制Web服务器定时器执行事务!
- hdu 4609
- Oracle EM错误,java.lang.Exception: Exception in sending Request :: null
- c#第四次作业 c#操作MySQL数据库
- 相位对焦与反差对焦
- C语言 switch语句的使用总结
- Unity中NullReferenceException: (null) UnityEditor.SerializedObject..ctor (UnityEngine.Object[] 问题
- linux程序设计——进程管道(第十三章)
- jQuery插件flexigrid使用总结
- LeetCode-String to Integer (atoi) -解题报告