一句話題解
阿新 • • 發佈:2018-10-04
其他 最長 space isp 方案 不知道 ceil blank 所有
HDU 5885 - XM Reserves
題意:給你n*m的矩陣P , 以及給定的半徑r, 對於P[i,j]與其距離嚴格小於r的點P1[i1,j1], P[i,j]對其有一個貢獻值v = P[i1,j1] / [(dis(p, p1)+1];
求所有點中最大的V;
思路 :如果暴力求解復雜度為 O(n*m*r*r)顯然不能接受, 菜的真實 , 看了一下大佬的題解, 真心不知道大佬們是怎麽想到FFT的,全世
界就我不會系列~~~;
#include <stdio.h> #include <iostream> #include <stringView Code.h> #include <algorithm> #include <math.h> using namespace std; const double PI = acos(-1.0); struct complex { double r,i; complex(double _r = 0,double _i = 0) { r = _r; i = _i; } complex operator +(const complex &b) { return complex(r+b.r,i+b.i); } complexoperator -(const complex &b) { return complex(r-b.r,i-b.i); } complex operator *(const complex &b) { return complex(r*b.r-i*b.i,r*b.i+i*b.r); } }; void change(complex 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; } } void fft(complex y[],int len,int on) { change(y,len); for(int h = 2;h <= len;h <<= 1) { complex wn(cos(-on*2*PI/h),sin(-on*2*PI/h)); 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(on == -1) for(int i = 0;i < len;i++) y[i].r /= len; } double dis(int x, int y) { return (double)sqrt(x*x+y*y); } //const int maxn = 1e6+7 // 莫名超時??? const int maxn = 1<<21; complex a[maxn], b[maxn]; int n, m ; double r; int main() { while(scanf("%d%d%lf\n",&n,&m,&r ) != EOF) { int R = ceil(r); int M = m+2*R; int len = 1; while(len <= M*M) len <<= 2; for(int i = 0; i < len; i++) { a[i] = complex(0.0,0.0); b[i] = complex(0.0, 0.0); } for(int i = 0; i < n; i++) { for(int j = 0; j < m; j++) { scanf("%lf", &a[i*M+j].r); } } for(int i = -R; i <= R; i++) { for(int j = -R; j <= R; j++) { double d = dis(i, j); if(d < r) { b[(i+R)*M + j+R] =complex( (1.0)/(d+1.0), 0.0); } } } fft(a, len, 1); fft(b, len, 1); for(int i = 0; i< len; ++i) a[i] = a[i]*b[i]; fft(a, len, -1); double ans = 0; for(int i = 0; i < n; i++) for(int j = 0; j < m; j++) { ans = max(ans, a[(i+R)*M+j+R].r); } printf("%.3lf\n", ans); } return 0; }
HDU 1402 - A * B Problem Plus
高精度乘法, 但顯然不能用樸素算法求解O(n*n), 理所當然的FFT 入門題
HDU 4609 - 3-idiots
題意 : 給你n根長度為a[i] 的木棍, 問你從其中任選三根能組成三角形的概率是多少 ?
FFT老題, 用數組b[i]表示長度為i的木棍的數量, 模擬多項式sum[i] = b[i]*b[i]可以得到兩根木棍相加長度為 i 的有多少種可能,減去不合法的 :
自身相加的和重復組合的,再前綴和處理一下, 對每一個a[i] 假設其為最長的一根時能組成的三角形的方案 : ans = sum[n-1] - sum[a[i]];
ans 再減去一些不合法的方案 : 一個大的加一個小的, 兩個大的, 他本身加其他;
#include <stdio.h> #include <iostream> #include <string.h> #include <algorithm> #include <math.h> using namespace std; const double PI = acos(-1.0); struct complex { double r,i; complex(double _r = 0,double _i = 0) { r = _r; i = _i; } complex operator +(const complex &b) { return complex(r+b.r,i+b.i); } complex operator -(const complex &b) { return complex(r-b.r,i-b.i); } complex operator *(const complex &b) { return complex(r*b.r-i*b.i,r*b.i+i*b.r); } }; void change(complex 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; } } void fft(complex y[],int len,int on) { change(y,len); for(int h = 2;h <= len;h <<= 1) { complex wn(cos(-on*2*PI/h),sin(-on*2*PI/h)); 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(on == -1) for(int i = 0;i < len;i++) y[i].r /= len; } double dis(int x, int y) { return (double)sqrt(x*x+y*y); } //const int maxn = 1e6+7 // 莫名超時??? const int maxn = 1<<21; complex a[maxn], b[maxn]; int n, m ; double r; int main() { while(scanf("%d%d%lf\n",&n,&m,&r ) != EOF) { int R = ceil(r); int M = m+2*R; int len = 1; while(len <= M*M) len <<= 2; for(int i = 0; i < len; i++) { a[i] = complex(0.0,0.0); b[i] = complex(0.0, 0.0); } for(int i = 0; i < n; i++) { for(int j = 0; j < m; j++) { scanf("%lf", &a[i*M+j].r); } } for(int i = -R; i <= R; i++) { for(int j = -R; j <= R; j++) { double d = dis(i, j); if(d < r) { b[(i+R)*M + j+R] =complex( (1.0)/(d+1.0), 0.0); } } } fft(a, len, 1); fft(b, len, 1); for(int i = 0; i< len; ++i) a[i] = a[i]*b[i]; fft(a, len, -1); double ans = 0; for(int i = 0; i < n; i++) for(int j = 0; j < m; j++) { ans = max(ans, a[(i+R)*M+j+R].r); } printf("%.3lf\n", ans); } return 0; }View Code
一句話題解