1. 程式人生 > >一句話題解

一句話題解

其他 最長 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 <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

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

  

  

  

  

一句話題解