标签:== 重复 半径 color gif max 高精度 iot ons
题意:给你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 <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; }
高精度乘法, 但显然不能用朴素算法求解O(n*n), 理所当然的FFT 入门题
题意 : 给你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; }
标签:== 重复 半径 color gif max 高精度 iot ons
原文地址:https://www.cnblogs.com/mrh-acmer/p/9741389.html