博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[报告]ZJU 3648 Gao the Grid II
阅读量:6874 次
发布时间:2019-06-26

本文共 1660 字,大约阅读时间需要 5 分钟。

Abstract

ZJU 3648 Gao the Grid II

组合计数 不等式

 

Body

第一次把一场浙大月赛的题目全部做完呢~对于小女这样的菜鸟来说,算是不小的成就,好开心呀~

Source

Description

求N x M的矩形网格中有多少个以格点为顶点的锐角三角形。

Solution

据说本题数据很水,可以O(N^4)乱搞过去。不过这里还是说说正经做法。

首先注意到任意一个三角形可以唯一确定一个包含它的最小矩形,并且三角形至少有一个顶点在矩形的顶点上。

然后可以发现,对于任意的锐角三角形,三个顶点一定都在矩形的边上。

如果我们知道给定大小的矩形上有多少个锐角三角形,我们就可以枚举矩形大小,算出大矩形内有多少个小矩形,乘上小矩形上的锐角三角形个数,最后再求和就可以了。

现在问题就是求给定大小的矩形上有多少个锐角三角形。设矩形大小为(i, j),不妨令三角形的一个顶点在(i, j)上,如图。

现在要求alpha和beta都是锐角,用向量点积或者余弦定理都可以解出q*j>p*(i-p)以及p*i>q*(j-q),且0<p<=i以及0<q<j。枚举p的话,q的解集是可以O(1)算出来的(一个一次不等式解集和一个二次不等式解集的交)。顶点在其它三个点的情况类似。

这样对于给定的(i, j),锐角三角形的个数就可以O(N)求出。所以对于所有的(i, j),只需要O(N^3)时间预处理统计。

具体实现时候,我用了当p递增时关于q的二次不等式解集的两个边界一增一减的性质,这样可以避免浮点运算和一大堆乱七八糟的讨论。

Code

#include 
#include
#include
#include
using namespace std;typedef long long ll;int N, M;ll cnt[111][111];ll solve(int i, int j) { ll res = 0; int p, q, l = 0, r = j; for (p = 1; p <= i; ++p) { while (l
l*(j-l)) ++l; while (r>0 && l<=r && p*i>r*(j-r)) --r; q = p*(i-p)/j; if (q >= r) res += max(0, j-q-1); else if (q >= l) res += max(0, j-r-1); else res += max(0, j-r-1)+max(0, l-q-1); } return res;}int main() { int i, j, p, q, l, r; for (i = 1; i <= 100; ++i) for (j = 1; j <= 100; ++j) cnt[i][j] = solve(i, j)+solve(j, i)<<1; while (cin>>N>>M) { ll ans = 0; for (i = 1; i <= N; ++i) for (j = 1; j <= M; ++j) ans += cnt[i][j]*(N-i+1)*(M-j+1); cout<
<<'\n'; } return 0;}

转载于:https://www.cnblogs.com/jffifa/archive/2012/10/02/2710360.html

你可能感兴趣的文章
我的友情链接
查看>>
在linux6上安装RAC时多路径的权限设置
查看>>
[转载] 七龙珠第一部——第037话 忍者出现
查看>>
网络数据通信加密系统中加密解密流程
查看>>
PXE+KickStart无人值守安装RHEL
查看>>
十年,站酷已成设计论坛霸主,博客园却成无兵之将
查看>>
ansible安装
查看>>
使用bind搭建DNS服务器
查看>>
Windows server 2008R2 DHCP服务器
查看>>
计算机网络笔记--数据链路层(一)
查看>>
我的友情链接
查看>>
Java方法重载注意事项
查看>>
爱创课堂每日一题第五十九天- javascript继承的6种方法
查看>>
16.1 Tomcat介绍 16.2 安装jdk 16.3 安装Tomcat
查看>>
JS 正则表达式用法
查看>>
文档查看cat_more_less_head_tail
查看>>
python课堂笔记之django-day01(4)
查看>>
九月十九日作业
查看>>
Shell工作笔记01
查看>>
项目、软件开发过程中版本术语
查看>>