题意:


给你一个R*C的棋盘,棋盘上的棋子会攻击,一个棋子会覆盖它所在的行,它所在的列,和它所在的从左上到右下的对角线,那么问这个棋盘上没有被覆盖的棋盘格子数。数据范围R,C,N<=50000

思路:


直接做肯定会超时,所以需要一种\(nlogn\)的算法。我们一步一步来。

首先,我们肯定需要给被覆盖的行被覆盖的列做上标记,visx标记被覆盖的行,visy标记被覆盖的列,visd标记被覆盖的对角线

那么就是 visx[r]=1,visy[c]=1,visd[r-c+C]=1,给对角线这么标号避免了负的下标,即从右上角开始到左下角从1标到R-1+C,而且下面还会用到。

然后,如果我们不考虑被覆盖的对角线,那么没有被覆盖的格子数就是未被覆盖的行数\(*\)未被覆盖的列数,但是还有被覆盖的对角线。

下面,我们设为行的覆盖情况的集合为{r1,r2,r3,ri,rR}其中下标代表行号,值为1或0,代表是否被覆盖,1是没被覆盖,0是被覆盖,列也一样{c1,c2,c3,cj,cC},我们再设对角线的{d1,d2,d3,dk,dx+y-1}但这里的值是这个对角线未被覆盖的值,

然后我们看,一开始我们没有考虑对角线,现在我们就要把对角线覆盖的部分从行列未覆盖的部分减去,那么我们就要知道在未考虑对角线覆盖情况下每个对角线没有被覆盖的格子数,然后根据visd把未被行列覆盖但被对角线覆盖的格子数减去。

那么每个对角线,那么标号为k的对角线的未被覆盖格子数是什么

\[\sum\sum(r_i\times c_j)(i-j+C=k)=d_k$$。
那么我们就发现了,$ri\times cj$就相当于系数相乘,下标i-j+C就相当于指数相加,那么这时候就可以把它转化为多项式了,相当于两个多项式相乘,那么就要用到FFT了。
下面就是多项式系数赋值了。首先行的多项式就这么顺序赋值即可,又因为指数相加结果是i-j+C,那么行的指数就是i,列的指数就是拿j的系数做指数C-j的系数,这样相加就可以得到上面的求和公式的效果了。套FFT模板搞一下就行了,最后再结合visd去重即可。

```cpp
# include <cstdio>
# include <cstring>
# include <cstdlib>
# include <iostream>
# include <vector>
# include <queue>
# include <stack>
# include <map>
# include <complex>
# include <set>
# include <cmath>
# include <algorithm>
using namespace std;
# define lowbit(x) ((x)&(-x))
const double pi=acos(-1.0);
# define eps 1e-8
# define MOD 1000000007
# define INF 1000000000
# define mem(a,b) memset(a,b,sizeof(a))
# define FOR(i,a,n) for(int i=a; i<=n; ++i)
# define FDR(i,a,n) for(int i=a; i>=n; --i)
# define bug puts("H");
# define lch p<<1,l,mid
# define rch p<<1|1,mid+1,r
# define mp make_pair
# define pb push_back
typedef pair<int,int> PII;
typedef vector<int> VI;
# pragma comment(linker, "/STACK:1024000000,1024000000")
typedef long long LL;
inline int Scan() {
int x=0,f=1; char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-') f=-1; ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0'; ch=getchar();}
return x*f;
}
inline void Out(int a) {
if(a<0) {putchar('-'); a=-a;}
if(a>=10) Out(a/10);
putchar(a%10+'0');
}
const int N=50005;
//Code begin....

typedef complex<double> cmx;
int a[N<<2], b[N<<2];
cmx x[N<<2], y[N<<2];
bool visr[N<<2], visc[N<<2], visd[N<<2];
struct Node{int x, y;}node[N];

void change(cmx x[], int len) {
int i, j, k;
for(i=1, j=len>>1; i<len-1; ++i) {
if(i<j) swap(x[i],x[j]);
k=len>>1;
while(j>=k) j-=k, k>>=1;
if(j<k) j+=k;
}
}
void fft(cmx x[], int len, int on) {
change(x,len);
for(int i=2; i<=len; i<<=1) {
cmx wn(cos(-on*2*pi/i),sin(-on*2*pi/i));
for(int j=0; j<len; j+=i) {
cmx w(1,0);
FOR(k,j,j+i/2-1) {
cmx u=x[k], v=x[k+i/2]*w;
x[k]=u+v; x[k+i/2]=u-v; w*=wn;
}
}
}
if(on==-1) FOR(i,0,len-1) x[i]/=len;
}
int main()
{
int T, r, c, R, C, n;
scanf("%d",&T);
FOR(cas,1,T) {
mem(visr,0); mem(visc,0); mem(visd,0); mem(a,0); mem(b,0); r=0; c=0;
LL ans=0;
scanf("%d%d%d",&R,&C,&n);
FOR(i,1,n) scanf("%d%d",&node[i].x,&node[i].y), visr[node[i].x]=visc[node[i].y]=visd[node[i].x-node[i].y+C]=true;
FOR(i,1,R) if (!visr[i]) a[i]=1, ++r;
FOR(i,1,C) if (!visc[i]) b[C-i]=1, ++c;
ans=(LL)r*c;
int len=1;
while (len<=R+C) len<<=1;
FOR(i,0,len-1) x[i]=cmx(a[i],0), y[i]=cmx(b[i],0);
fft(x,len,1); fft(y,len,1);
FOR(i,0,len-1) x[i]=x[i]*y[i];
fft(x,len,-1);
FOR(i,0,len-1) if (visd[i]) ans-=(int)(x[i].real()+0.5);
printf("Case %d: %lld\n",cas,ans);
}
return 0;
}

```\]

UVA 12633 Super Rooks on Chessboard(FFT)的更多相关文章

  1. UVA 12633 Super Rooks on Chessboard [fft 生成函数]

    Super Rooks on Chessboard UVA - 12633 题意: 超级车可以攻击行.列.主对角线3 个方向. R * C 的棋盘上有N 个超级车,问不被攻击的格子总数. 行列好好做啊 ...

  2. UVA 12633 Super Rooks on Chessboard ——FFT

    发现对角线上的和是一个定值. 然后就不考虑斜着,可以处理出那些行和列是可以放置的. 然后FFT,统计出每一个可行的项的系数和就可以了. #include <map> #include &l ...

  3. [UVA 12633] Super Rooks on Chessboard FFT+计数

    如果只有行和列的覆盖,那么可以直接做,但现在有左上到右下的覆盖. 考虑对行和列的覆盖情况做一个卷积,然后就有了x+y的非覆盖格子数. 然后用骑士的左上到右下的覆盖特判掉那些x+y的格子就可以了. 注意 ...

  4. UVA 12633 Super Rooks on Chessboard (生成函数+FFT)

    题面传送门 题目大意:给你一张网格,上面有很多骑士,每个骑士能横着竖着斜着攻击一条直线上的格子,求没被攻击的格子的数量总和 好神奇的卷积 假设骑士不能斜着攻击 那么答案就是没被攻击的 行数*列数 接下 ...

  5. UVa12633 Super Rooks on Chessboard(容斥 + FFT)

    题目 Source http://acm.hust.edu.cn/vjudge/problem/42145 Description Let’s assume there is a new chess ...

  6. UVA12633 Super Rooks on Chessboard

    题目描述 题解: 第一眼满眼骚操作,然后全部否掉. 然后屈服于题解,才发现这题这么执掌. 首先,如果这个东西是普通的车,那我们可以记录一下$x,y$的覆盖情况,然后减一下; 但是这个可以斜着走. 所以 ...

  7. UVA - 12298 Super Poker II NTT

    UVA - 12298 Super Poker II NTT 链接 Vjudge 思路 暴力开个桶,然后统计,不过会T,用ntt或者fft,ntt用个大模数就行了,百度搜索"NTT大模数&q ...

  8. UVA - 11134 Fabled Rooks[贪心 问题分解]

    UVA - 11134 Fabled Rooks We would like to place n rooks, 1 ≤ n ≤ 5000, on a n × n board subject to t ...

  9. uva 11134 - Fabled Rooks(问题转换+优先队列)

    题目链接:uva 11134 - Fabled Rooks 题目大意:给出n,表示要在n*n的矩阵上放置n个车,并且保证第i辆车在第i个区间上,每个区间给出左上角和右小角的坐标.另要求任意两个车之间不 ...

随机推荐

  1. SSIS 变量、参数和表达式

    动态包对象包括变量,参数和表达式.变量主要为包提供一种对象之间相互通信的方法,变量的值是可以更新的.而参数不同于变量,参数的值在包中是不能修改的,只能通过外部来设置参数.表达式可以引用变量.参数.常量 ...

  2. jenkins 自动上传代码到nexus 私库

    1.jenkins 项目配置上传 2.jenkins 访问私库下载配置 -X clean install 3.maven 配置文件 /usr/local/maven/conf/settings.xml ...

  3. requests.get()解析

    1.requests.get(url, params=None, headers=None, cookies=None, auth=None, timeout=None) Sends a GET re ...

  4. Mac OS下Appium环境搭建及Genymotion模拟器安装

    说明:本机Mac本上已经安装的有:Python3.JDK.Node.js. Selenium Appium环境搭建 Step1:安装Appium Python Client库 1,命令:pip ins ...

  5. 高可用OpenStack(Queen版)集群-13.分布式存储Ceph

    参考文档: Install-guide:https://docs.openstack.org/install-guide/ OpenStack High Availability Guide:http ...

  6. Vue02

    3.Vue对象提供的属性功能 过滤器,就是vue允许开发者自定义的文本格式化函数,可以使用在两个地方:输出内容和操作数据中. 定义过滤器的方式有两种. 1 使用Vue.filter()进行全局定义 V ...

  7. 2013第四届蓝桥杯C/C++ B组

    题目标题: 高斯日记:Excel 大数学家高斯有个好习惯:无论如何都要记日记. 他的日记有个与众不同的地方,他从不注明年月日,而是用一个整数代替,比如:4210 后来人们知道,那个整数就是日期,它表示 ...

  8. XSS构造技巧

    利用字符编码: 百度曾经出过一个XSS漏洞,在一个<script>标签中输出一个变量,其中转义了双引号: var redirectUrl="\";alert(/XSS/ ...

  9. Redis Jedis简介

    Redis是一种基于内存类型的数据存储工具 Jedis是一个用java写的Redis数据库操作的客户端,通过Jedis,可以很方便的对redis数据库进行操作.Jedis通过Jedis Pool进行R ...

  10. 第二阶段Sprint1

    昨天:进行第二阶段第一次站立会议,讨论冲刺阶段,目标,任务认领 今天:实现视频录制,共享平台的视频下载和上传 遇到的问题:调手机摄像头没问题,共享平台怎么办