UVA12633:Super Rooks on Chessboard (FFT)

来源:互联网 发布:阅读杂志的软件 编辑:程序博客网 时间:2024/06/03 12:29

题目传送门:https://cn.vjudge.net/problem/UVA-12633


题目大意:现在有一个r*c的白色棋盘,上面有n个棋子。每个棋子会将它所在行和所在列,以及所在主对角线染黑(主对角线就是左上到右下)。问最终有多少个白色格子。不超过20组数据,r,c,n<=50000。


题目分析:做了几道CF的题愉悦身心之后,我又开始刷回FFT的题了(虽然这题是水题)。

如果每个棋子只染所在行和列,那么这就是个简单的计数问题。现在我们需要知道每个棋子所在的主对角线还有多少没有染成黑色。由于同一条主对角线上的格子,横纵坐标之差为定值,不妨将没染的行,列设为1,将列翻转,然后做FFT即可。

难得的FFT20分钟1A。


CODE:

#include<iostream>#include<string>#include<cstring>#include<cmath>#include<cstdio>#include<cstdlib>#include<stdio.h>#include<algorithm>using namespace std;const int maxn=200000;const double pi=acos(-1.0);typedef long long LL;struct Complex{    double X,Y;    Complex (double a=0.0,double b=0.0) : X(a),Y(b) {}} ;Complex operator+(Complex a,Complex b){return Complex(a.X+b.X,a.Y+b.Y);}Complex operator-(Complex a,Complex b){return Complex(a.X-b.X,a.Y-b.Y);}Complex operator*(Complex a,Complex b){return Complex(a.X*b.X-a.Y*b.Y,a.X*b.Y+a.Y*b.X);}int Rev[maxn];Complex A[maxn];Complex B[maxn];bool fx[maxn];bool fy[maxn];int numx,numy;int px[maxn];int py[maxn];int t,n,r,c;LL ans;int N,Lg;void DFT(Complex *a,double f){    for (int i=0; i<N; i++)        if (i<Rev[i]) swap(a[i],a[ Rev[i] ]);    for (int len=2; len<=N; len<<=1)    {        int mid=len>>1;        double ang=2.0*pi/((double)len);        Complex e( cos(ang) , f*sin(ang) );        for (Complex *p=a; p!=a+N; p+=len)        {            Complex wn(1.0,0.0);            for (int i=0; i<mid; i++)            {                Complex temp=wn*p[mid+i];                p[mid+i]=p[i]-temp;                p[i]=p[i]+temp;                wn=wn*e;            }        }    }}void FFT(){    for (int i=0; i<N; i++)    {        Rev[i]=0;        for (int j=0; j<Lg; j++)            if ( i&(1<<j) ) Rev[i]|=( 1<<(Lg-j-1) );    }    DFT(A,1.0);    DFT(B,1.0);    for (int i=0; i<N; i++) A[i]=A[i]*B[i];    DFT(A,-1.0);    for (int i=0; i<N; i++) A[i].X/=((double)N);}int main(){    freopen("12633.in","r",stdin);    freopen("12633.out","w",stdout);    scanf("%d",&t);    for (int g=1; g<=t; g++)    {        scanf("%d%d%d",&r,&c,&n);        for (int i=1; i<=r; i++) fx[i]=false;        for (int i=1; i<=c; i++) fy[i]=false;        for (int i=1; i<=n; i++)        {            scanf("%d%d",&px[i],&py[i]);            fx[ px[i] ]=true;            fy[ py[i] ]=true;        }        numx=numy=0;        for (int i=1; i<=r; i++) if (fx[i]) numx++;        for (int i=1; i<=c; i++) if (fy[i]) numy++;        ans=0;        ans-=( (long long)numx*(long long)c+(long long)numy*(long long)r );        ans+=( (long long)r*(long long)c+(long long)numx*(long long)numy );        for (int i=0; i<r; i++)            if (fx[i+1]) A[i]=Complex(0.0,0.0);            else A[i]=Complex(1.0,0.0);        for (int i=0; i<c; i++)            if (fy[i+1]) B[i]=Complex(0.0,0.0);            else B[i]=Complex(1.0,0.0);        for (int i=0; i<c-i-1; i++) swap(B[i],B[c-i-1]);        N=1,Lg=0;        while (N<r+c) N<<=1,Lg++;        for (int i=r; i<N; i++) A[i]=Complex(0.0,0.0);        for (int i=c; i<N; i++) B[i]=Complex(0.0,0.0);        FFT();        for (int i=1; i<=n; i++)        {            int x=px[i]-1,y=py[i]-1;            y=c-y-1;            ans-=( (int)floor(A[x+y].X+0.5) );            A[x+y].X=0.0;        }        printf("Case %d: %lld\n",g,ans);    }    return 0;}