先看第一题,有n*m个点,求在这些点中,有多少条直线,经过了至少两点,且不是水平的也不是竖直的。

  分析:由于对称性,我们只要求一个方向的线即可。该题分成两个过程,第一个过程是求出n*m的矩形中,dp[i][j]代表在这个矩形中终点是到(i,j)这个点的满足题意的直线条数,那么,用dp的话就可以得出递推关系:由长和宽分别小1的左右两个矩形中满足题意的线的条数减去他们共有的矩形中满足的线的条数(容斥减去重复部分),之后还要判断从最左上角的点(1,1)到(i,j)是否可以组成一条线,这个条件是gcd(i,j)是否等于1。

  之后第二个过程就是递推答案了,设ans[i][j]表示在这个矩形中满足题意的条数,那么同样的,可以由上面的容斥来递推,同时,还要加上这个矩形内到(i,j)这个点满足的条数,另外还要减去一半规模大小的到这个点的线的条数,因为如果(i,j)为(6,8),那么一半规模下,(1,1)到(3,4)这个点的线和到(6,8)这条线是重复的。

  这样就做完了题目(最后不要忘了乘以2)。具体见代码:

 #include <stdio.h>
#include <algorithm>
#include <string.h>
#include <iostream>
#include <vector>
#include <queue>
using namespace std;
typedef long long ll;
const int N = +; int dp[N][N];
int ans[N][N]; int gcd(int a,int b) {return a%b?gcd(b,a%b):b;} void init()
{
for(int i=;i<N;i++)
{
for(int j=;j<N;j++)
{
dp[i][j] = dp[i-][j] + dp[i][j-] - dp[i-][j-] + (gcd(i,j)==);
}
}
for(int i=;i<N;i++)
{
for(int j=;j<N;j++)
{
ans[i][j] = ans[i-][j] + ans[i][j-] - ans[i-][j-] + dp[i][j] - dp[i>>][j>>];
}
}
} int main()
{
init();
int n,m;
while(scanf("%d%d",&n,&m)==)
{
if(n== && m==) break;
printf("%d\n",*ans[n-][m-]);
}
}

  做出了这题,第二题就是类似的了。先在所有的点中枚举出选3个点的可能性,然后,减去一条水平或者竖直线上重复的,再减去同在一条斜线上重复的即可。相当类似,具体见代码吧:

 #include <stdio.h>
#include <algorithm>
#include <string.h>
#include <iostream>
#include <vector>
#include <queue>
using namespace std;
typedef long long ll;
const int N = +; ll dp[N][N];
ll ans[N][N]; int gcd(int a,int b) {return a%b?gcd(b,a%b):b;} void init()
{
for(int i=;i<N;i++)
{
for(int j=;j<N;j++)
{
dp[i][j] = dp[i-][j] + dp[i][j-] - dp[i-][j-] + (ll)(gcd(i,j)-);
}
}
for(int i=;i<N;i++)
{
for(int j=;j<N;j++)
{
ans[i][j] = ans[i-][j] + ans[i][j-] - ans[i-][j-] + dp[i][j];
}
}
} ll C(ll x) {return x*(x-)*(x-)/;} int main()
{
init();
int n,m;
int cnt = ;
while(scanf("%d%d",&n,&m)==)
{
if(n== && m==) break;
ll Ans = C((n+)*(m+)) - (n+)*C(m+) - (m+)*C(n+);
Ans -= *ans[n][m];
cout<<"Case "<<cnt++<<": "<<Ans<<endl;
}
}

  

  但是,这两题都要注意的地方是,递推dp时三个矩形都是在右下角的(因为向下或者向右平移一个单位的话条数是不变的),这样递推起来的话只要再考虑从(1,1)这个点到(i,j)这个点的情况即可;而递推ans的时候,矩形是偏左上方的,那么,只要再加上整个大矩形内到(i,j)这个点的情况即可。当然,纯属个人理解。

UVA 1393 Highways,UVA 12075 Counting Triangles —— (组合数,dp)的更多相关文章

  1. UVA 12075 - Counting Triangles(容斥原理计数)

    题目链接:12075 - Counting Triangles 题意:求n * m矩形内,最多能组成几个三角形 这题和UVA 1393类似,把总情况扣去三点共线情况,那么问题转化为求三点共线的情况,对 ...

  2. uva 1393 - Highways(容斥原理)

    题目连接:uva 1393 - Highways 题目大意:给定一个m∗n的矩阵,将矩阵上的点两两相连,问有多少条直线至少经过两点. 解题思路:头一次做这样的题目,卡了一晚上. dp[i][j]即为i ...

  3. UVA 12075 Counting Triangles

    https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_probl ...

  4. UVa 1393 - Highways(数论)

    链接: https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem& ...

  5. UVA 1393 Highways(数学思想)

    题意:给你n.m(n,m<=200),问你有多少条非水平.非垂直的直线有多少条经过至少两个点 题解:我们需要枚举的是只画一条线的矩形,对于大小a*b的矩形必须保证gcd(a,b)=1才能不重复 ...

  6. UVA 1393 Highways

    https://vjudge.net/problem/UVA-1393 题意: a*b的点阵中能画多少条非水平非竖直的直线 方向‘/’ 和 方向 ‘\’ 对称 枚举直线所在矩形的i*j 直线可能重复的 ...

  7. UVa 1393 (容斥原理、GCD) Highways

    题意: 给出一个n行m列的点阵,求共有多少条非水平非竖直线至少经过其中两点. 分析: 首先说紫书上的思路,编程较简单且容易理解.由于对称性,所以只统计“\”这种线型的,最后乘2即是答案. 枚举斜线包围 ...

  8. hdu 1396 Counting Triangles(递推)

    Counting Triangles Problem Description Given an equilateral triangle with n thelength of its side, p ...

  9. Counting Triangles(hd1396)

    Counting Triangles Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Other ...

随机推荐

  1. [Tarjan系列] Tarjan算法求无向图的双连通分量

    这篇介绍如何用Tarjan算法求Double Connected Component,即双连通分量. 双联通分量包括点双连通分量v-DCC和边连通分量e-DCC. 若一张无向连通图不存在割点,则称它为 ...

  2. 2-MySQL DBA笔记-MySQL安装部署和入门

    第2章 MySQL安装部署和入门 第1章介绍了MySQL的一些基础知识,本章将为读者介绍MySQL的部署.安装及一些常用命令和参数的设置.2.1 如何选择MySQL版本 在选择MySQL的版本时,要根 ...

  3. Linux设备驱动中的软件架构思想

    目录 更新记录 一.Linux驱动的软件架构 1.1 出发点 1.2 分离思想 1.3 分层思想 二.platform设备驱动 2.1 platform设备 2.2 platform驱动 2.3 pl ...

  4. sql 将英文句子中的单词首字母转换为大写

    create function dbo.pTitleCase(@StrIn nvarchar(max))returns nvarchar(max)as begin; declare @StrOut n ...

  5. 测试clang-format的格式化效果

    我自己写的业余框架已告一段落,主体功能已完成,剩下的就是优化.第一个要优化的,就是代码格式.我一直是用编辑器写代码的,从之前的UltraEdit到notepad++到sublime text,再到现在 ...

  6. python学习笔记:安装boost python库以及使用boost.python库封装

    学习是一个累积的过程.在这个过程中,我们不仅要学习新的知识,还需要将以前学到的知识进行回顾总结. 前面讲述了Python使用ctypes直接调用动态库和使用Python的C语言API封装C函数, C+ ...

  7. 01_Hive简介及其工作机制

    1.Hive简介 Hive是一个基于Hadoop的一个数据仓库工具,可以将结构化的数据文件映射为一个表.并提供类SQL查询功能, 可以将sql语句转换为MapReduce任务运行.其优点是学习成本低, ...

  8. 为什么Microsoft Office 2016安装时不能自选安装组件和安装路径?

    使用特别版本的安装镜像文件 SW_DVD5_Office_Professional_Plus_2016_64Bit_ChnSimp_MLF_X20-42426.iso,请自行搜索和下载 文件: SW_ ...

  9. 编译原理实战——使用Lex/Flex进行编写一个有一定词汇量的词法分析器

    编译原理实战--使用Lex/Flex进行编写一个有一定词汇量的词法分析器 by steve yu 2019.9.30 参考文档:1.https://blog.csdn.net/mist14/artic ...

  10. Oracle数据库结构

    之前写了一篇文章<Oracle-知识结构漫谈> 粗略的介绍了Oracle数据库接口,在这里再更加详细的描述一下,当做是对原有知识的巩固,温故知新. Oracle体系结构数据库的体系结构是从 ...