码迷,mamicode.com
首页 > 其他好文 > 详细

一句话题解

时间:2018-10-04 11:20:05      阅读:221      评论:0      收藏:0      [点我收藏+]

标签:==   重复   半径   color   gif   max   高精度   iot   ons   

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

 

  

  

 

  

  

 

一句话题解

标签:==   重复   半径   color   gif   max   高精度   iot   ons   

原文地址:https://www.cnblogs.com/mrh-acmer/p/9741389.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!