HDU5621——数学应用(多边形内对角线交点个数) + 数论 + unsigned long long的应用
2016-02-17 20:18
501 查看
题目描述:
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 713 Accepted Submission(s): 238
Problem Description
Our lovely KK has a difficult mathematical problem:He points N(2≤N≤105) points
on a circle,there are all different.Now he's going to connect the N points
with each other(There are no three lines in the circle to hand over a point.).KK wants to know how many points are there in the picture(Including the dots of boundary).
Input
The first line of the input file contains an integer T(1≤T≤10),
which indicates the number of test cases.
For each test case, there are one lines,includes a integer N(2≤N≤105),indicating
the number of dots of the polygon.
Output
For each test case, there are one lines,includes a integer,indicating the number of the dots.
Sample Input
Sample Output
题意:
一个圆周上点下了互不重合的N(2≤N≤105)个点,将这N个点两两相连(圆内没有三条线交于一个点的情况),图形中一共有多少个交点(包括边界上的点)。
解析:
同样,这也是一道找规律的题目,将这N个点两两相连,当N>3时,在外部则形成了一个多边形,然后内部的连线则是多边形的对角线,而这道题便转换为多边形内对角线交点个数的问题,即原问题转换成数学问题:
给定一个凸N边形,满足性质:任何三条对角线都不交于同一点.在这样一个多边形的内部,它的所有对角线共形成多少个交点?
由于每一个交点对应着两条相交的对角线,而两条相交的对角线确定一个四边形,所以计算交点的个数即是计算多边形内四边形的个数,所以原问题又转换为多边形内四边形的个数,而四边形四个点,所以这就是我们熟悉的组合问题了(在N个点中任意找四个点形成一个四边形),那么交点个数=四边形个数=C(N,N-4).考虑特殊情况后,很快便得出完整代码:
于是,我便开始纳闷,为什么会这样呢?规律都正确了,为什么会得出Wrong Answer呢?
然后我注意到了N的取值范围,N<=10^5,所以我考虑是不是long long的数据范围不够大?于是我很快便得出以下代码:
于是我想不明白了,数据改为unsigned long long类型了,已经是整型范围内最大的数据类型了,难道还是超过最大范围吗?于是我重新看了一下N的取值范围,然后发现四个连乘之后,数据达到了10^20级别,而下面是各种数据类型的数据范围:
然后发现unsigned long long的最大值也只是10^19次方级别的数据,而四个连乘之后数据范围明显超过了unsigned
long long的最大值,那么我们要怎么做才能得到正确答案呢?我们发现,连续的两个数必定有一个是偶数,连续的三个数必定有一个是3的倍数,同理,连续的四个数必定有一个是4的倍数,所以呢,我们可以不必要直接把四个含有N的表达式全部相乘,可以连续两个乘过之后,除以2,然后再乘一个,除以3,这样的话,在N取得最大值10^5的情况下,前面四个连乘后得出的结果为:16665666684999900000,数据范围在unsign
long long之内,这样的话,我们解决了问题。再除以4,这样的话,所以得出以下完整代码:
总结:这道题其实不难,考的是数学应用,但是这道题考察了平时会比较忽略的知识(unsigned long long,溢出最大数据范围等问题),所以呢,我们才一时找不出错误,这更警醒我们要注重基础,多了解一点总是没有害处的。然后平时要多积累,注意数学问题之间的转换,可以化难为易,并且转换成我们能够解决的问题。
KK's Point
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 713 Accepted Submission(s): 238
Problem Description
Our lovely KK has a difficult mathematical problem:He points N(2≤N≤105) points
on a circle,there are all different.Now he's going to connect the N points
with each other(There are no three lines in the circle to hand over a point.).KK wants to know how many points are there in the picture(Including the dots of boundary).
Input
The first line of the input file contains an integer T(1≤T≤10),
which indicates the number of test cases.
For each test case, there are one lines,includes a integer N(2≤N≤105),indicating
the number of dots of the polygon.
Output
For each test case, there are one lines,includes a integer,indicating the number of the dots.
Sample Input
2 3 4
Sample Output
3 5
题意:
一个圆周上点下了互不重合的N(2≤N≤105)个点,将这N个点两两相连(圆内没有三条线交于一个点的情况),图形中一共有多少个交点(包括边界上的点)。
解析:
同样,这也是一道找规律的题目,将这N个点两两相连,当N>3时,在外部则形成了一个多边形,然后内部的连线则是多边形的对角线,而这道题便转换为多边形内对角线交点个数的问题,即原问题转换成数学问题:
给定一个凸N边形,满足性质:任何三条对角线都不交于同一点.在这样一个多边形的内部,它的所有对角线共形成多少个交点?
由于每一个交点对应着两条相交的对角线,而两条相交的对角线确定一个四边形,所以计算交点的个数即是计算多边形内四边形的个数,所以原问题又转换为多边形内四边形的个数,而四边形四个点,所以这就是我们熟悉的组合问题了(在N个点中任意找四个点形成一个四边形),那么交点个数=四边形个数=C(N,N-4).考虑特殊情况后,很快便得出完整代码:
#include<cstdio> #include<algorithm> using namespace std; typedef long long ll; int main() { int T; ll N; while(scanf("%d",&T)==1&&T) { while(T--) { scanf("%I64d",&N); if(N==2) printf("2\n"); else if(N==3) printf("3\n"); else if(N>3) { ll sum = (N * (N - 1) * (N - 2) *(N - 3)) / 24; printf("%I64d\n",sum+N); } } } return 0; }提交答案后,却得出这样的回复:
于是,我便开始纳闷,为什么会这样呢?规律都正确了,为什么会得出Wrong Answer呢?
然后我注意到了N的取值范围,N<=10^5,所以我考虑是不是long long的数据范围不够大?于是我很快便得出以下代码:
#include<cstdio> #include<algorithm> using namespace std; typedef unsigned long long ull; int main() { int T; ull N; while(scanf("%d",&T)==1&&T) { while(T--) { scanf("%llu",&N); if(N==2) printf("2\n"); else if(N==3) printf("3\n"); else if(N>3) { ull sum = (N * (N - 1) * (N - 2) *(N - 3)) / 24; printf("%llu\n",sum+N); } } } return 0; }可依旧还是:
于是我想不明白了,数据改为unsigned long long类型了,已经是整型范围内最大的数据类型了,难道还是超过最大范围吗?于是我重新看了一下N的取值范围,然后发现四个连乘之后,数据达到了10^20级别,而下面是各种数据类型的数据范围:
然后发现unsigned long long的最大值也只是10^19次方级别的数据,而四个连乘之后数据范围明显超过了unsigned
long long的最大值,那么我们要怎么做才能得到正确答案呢?我们发现,连续的两个数必定有一个是偶数,连续的三个数必定有一个是3的倍数,同理,连续的四个数必定有一个是4的倍数,所以呢,我们可以不必要直接把四个含有N的表达式全部相乘,可以连续两个乘过之后,除以2,然后再乘一个,除以3,这样的话,在N取得最大值10^5的情况下,前面四个连乘后得出的结果为:16665666684999900000,数据范围在unsign
long long之内,这样的话,我们解决了问题。再除以4,这样的话,所以得出以下完整代码:
#include<cstdio> #include<algorithm> using namespace std; typedef unsigned long long int ull; int main() { int T; ull N; scanf("%d",&T); while(T--) { scanf("%I64u",&N); ull sum = N; if(N>3) sum += N * (N - 1) / 2 * (N - 2) / 3 * (N - 3) / 4; //ULL只有19位 printf("%I64u\n",sum); } return 0; }
总结:这道题其实不难,考的是数学应用,但是这道题考察了平时会比较忽略的知识(unsigned long long,溢出最大数据范围等问题),所以呢,我们才一时找不出错误,这更警醒我们要注重基础,多了解一点总是没有害处的。然后平时要多积累,注意数学问题之间的转换,可以化难为易,并且转换成我们能够解决的问题。
相关文章推荐
- 【iOS】UIPickerView -- 地址选择器:省/市/区
- 7.内存管理
- golang笔记——命令
- CentOS下编译php时的一些典型错误及解决办法
- 学无止境--新浪算法组的博文,都很好
- fragment
- linux命令手册
- vivado sdk生成elf文件出错:make: Interrupt/Exception caught (code = 0xc00000fd, addr = 0x4227d3)
- js判断字符串中出现次数最多的字符 并统计出现次数
- 流媒体平台框架开源EasyDarwin
- 《第五项修炼》阅读笔记
- Kali Linux 安全渗透教程<第三更>1.2 安全渗透所需工具
- 为了"魔兽世界默认高特效" — 时隔近6年的一次主机大升级
- solr对mysql中tinyint字段的处理方法
- TestNG英文全称
- 循环后缀(Cyclic suffix)
- Java中String创建原理深入分析
- 网络抓包过滤表达式
- ECMAScript
- 基于ssdb和mongodb的feed服务架构