UVA 12633 Super Rooks on Chessboard

【分析】
PDF实在是不好粘贴题面…而且另一个编辑器gg了…
那么这道题用a[i]表示第i行是否被占领,b[j]表示第j列是否被占领,是为0,否为1,观察发现一个点(i,j)所在对角线是i-j是常数,为了防止出现负数我们写作i+M-j。然后把列翻一下,ab数组卷积,没被彻底占领的对角线(用一个常数表示)的系数和即为答案。


【代码】

//UVA 12633
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define pi acos(-1)
#define ll long long
#define M(a) memset(a,0,sizeof a)
#define fo(i,j,k) for(i=j;i<=k;i++)
using namespace std;
const int mxn=200005;
bool vis[mxn];
ll ans;
int n,m,s,N,M,L,T;
int R[mxn];
struct E
{
    double r,f;
    E (double u,double v) {r=u,f=v;}
    E () {}
    E operator + (E u) {return E(r+u.r,f+u.f);}
    E operator - (E u) {return E(r-u.r,f-u.f);}
    E operator * (E u) {return E(r*u.r-f*u.f,r*u.f+f*u.r);}
    E operator / (int v) {return E(r/v,f/v);}
}a[mxn],b[mxn],c[mxn];
inline void FFT(E *a,int f)
{
    int i,j,k;
    fo(i,0,n-1) if(i<R[i]) swap(a[i],a[R[i]]);
    for(i=1;i<n;i<<=1)
    {
        E wn(cos(pi/i),f*sin(pi/i));
        for(j=0;j<n;j+=(i<<1))
        {
            E w(1,0);
            for(k=0;k<i;k++,w=w*wn)
            {
                E x=a[j+k],y=w*a[j+k+i];
                a[j+k]=x+y,a[j+k+i]=x-y;
            }
        }
    }
    if(f==-1) fo(i,0,n-1) a[i]=a[i]/n;
}
int main()
{
    int i,j,x,y,t;
    scanf("%d",&T);
    fo(t,1,T)
    {
        M(a),M(b),M(c),M(R),M(vis),L=0,ans=0;
        scanf("%d%d%d",&N,&M,&s);N--,M--;
        fo(i,0,N) a[i].r=1.0;
        fo(j,0,M) b[M-j].r=1.0;
        fo(i,1,s)
        {
            scanf("%d%d",&x,&y);x--,y--;
            vis[x+M-y]=1; 
            a[x].r=0.0,b[M-y].r=0.0;
        }
        n=max(N,M)+1,m=2*n;for(n=1;n<=m;n<<=1) L++;
        fo(i,0,n-1) R[i]=(R[i>>1]>>1)|((i&1)<<L-1);
        FFT(a,1),FFT(b,1);
        fo(i,0,n) c[i]=a[i]*b[i];
        FFT(c,-1);
        fo(i,0,N+M) if(!vis[i]) ans+=(ll)(c[i].r+0.5);
        printf("Case %d: %lld\n",t,ans);
    }
    return 0;
}
/*
2
6 6 1
5 3
6 6 3
3 4
5 3
5 6
*/
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值