题目描述:

  相似整数三角形的周长和为N(1<=N<=5000000),问这样的三角形组合有多少种(三角形是有序的)

样例:

  N为9时,一共有6种。

  (1, 1, 1) (1, 1, 1) (1, 1, 1)
  (1, 1, 1) (2, 2, 2)
  (2, 2, 2) (1, 1, 1)
  (1, 4, 4)
  (2, 3, 4)
  (3, 3, 3)

  要解决这题,我们先给出一个0(1)的时间复杂度求周长为N的整数三角形的个数的算法。

  设三角形三边为a1,a2,a3,a1+a2+a3=N,并且a1<=a2<=a3。

  a1最小,所以1<=a1<=N/3。算法的思路是将周长为N的三角形按照最小边分类,也就是

也就是要将N/3个整数加起来就是三角形个数的和了,我们算求和公式里面的某一项时,a1是定值,比如a1等于1时三角形的个数,a1等于2时三角形的个数。。。。。

  既然a1是定值,我们可以把a1的值先给a2和a3,因为a2和a3都比a1要大,先给a2和a3分配a1的长度,还剩下N-3*a1个长度,我们可以全部给a3,也就是说满足

  a3-a2<=N-3*a1。

  由三角形的性质,两长边之差小于第三边,也就是a3-a2<a1,就是a3-a2<=a1-1。

  现在a3与a2的差要满足两个限制条件了,一个是N-3a1,一个是a1-1。,一个随着递增一个递减,所以选择分段处理,分界点是a1等于N/4的时候。

    当1<=a1<=N/4时,这时候满足a1-1<=N-3*a1,所以我们只需要关注a1-1。

    对N分为奇数和偶数谈论

    当N是奇数时

      a1为1,a3与a2的和是偶数,差也是偶数,小于1的偶数的个数是1,所以a1等于1时,三角形个数为1

      a1为3,a3与a2的和是偶数,差也是偶数,小于3的偶数的个数是2,所以a1等于3时,三角形个数为2

      a1为5,a3与a2的和是偶数,差也是偶数,小于5的偶数的个数是3,所以a1等于5时,三角形个数为3

      。。。。。。。。。。。。。。。。。。

      当a1是1,3,5,7.........时三角形的个数是1,2,3,4..................

      a1为2,a3与a2的和是奇数,差也是奇数,小于2的奇数的个数是1,所以a1等于2时,三角形个数为1

      a1为4,a3与a2的和是奇数,差也是奇数,小于4的奇数的个数是2,所以a1等于4时,三角形个数为2

      a1为6,a3与a2的和是奇数,差也是奇数,小于6的奇数的个数是3,所以a1等于6时,三角形个数为3

      。。。。。。。。。。。。。。。。。。

      当a1是2,4,6,8.........时三角形的个数是1,2,3,4....................

    两者结合起来就是1,1,2,2,3,3,4,4...............这样的数列知道个数很方便求和的

    同理,当N为偶数时,三角形个数的数列是0,1,1,2,2,3,3,..........

    解决完前半段,我们来解决后半段

    当N/4+1<=a1<=N/3时,此时N-3*a1<=a1-1,所以我们只需要关注N-3*a1。

    我们先给a2和a3分配a1的长度,还剩下N-3*a1的长度,现在要满足a2<=a3,我们可以把0,1,2,.....(N-3*a1)/2的长度分为a2,一共是(N-3*a1)/2+1种方案。

    在a1从N/4+1增加到N/3的过程中,N-3*a1是公差为3的等差数列,间隔一个看,可以看作是两个公差为6的等差数列,公差为6的等差数列除以2得到的是公差为3的等差数列,所以后半段是由两个公差为3的等差数列组成,这个求和也很好求,所以得到了0(1)时间复杂度求周长为N的整数三角形的个数。代码里面GetNumber函数就是专门来求这个的。

  现在我们来看问题,每一种方案都可以提一个基三角形出来,然后所有的三角形都是这个三角形的整数倍数。我们先求N的约数prime[],约数的个数是m

  那么方案数

  我们已9来举例子,9的约数是1,3,9

  周长为1并且三边公约数为1的三角形个数是0,0*2^8=0

  周长为3并且三边公约数为1的三角形个数是1,1*2^2=4,对应的方案是(1,1,1),(1,1,1),(1,1,1)

                                   (1,1,1),(2,2,2)

                                   (2,2,2),(1,1,1)

                                   (3,3,3)

  周长为9并且三边公约数为1的三角形个数是2,2*2^0=2,对应的方案是(1,4,4)

                                   (2,3,4)

  一共加起来是6种,这里要求基三角形的公约数是1的原因是防止计算重复。

  那么现在问题来了,周长为L并且三边公约数为1的三角形该怎么算。

  周长为L并且三边公约数为1的三角形的个数=周长为L的三角形的个数减去周长为L三边公约数不为1的个数。

  周长为L的三角形个数我们上面已经讲了,有0(1)的时间复杂度的算法。

  现在求周长为L三边公约数不为1的个数

  设三角形三边为a1,a2,a3,最大公约数为c,我们将三边都除以c可以得到一个周长为L/c并且三边公约数为1的三角形。

  周长为L并且三边最大公约数为c的三角形的个数与周长为L/c并且公约数为1的三角形的个数是相等的,因为两者可以互相转换。

  将c分下类,c只能是L的约数且不能为1,那儿L/c就是L的约数但不包含L。

  周长为L并且三边公约数为1的三角形的个数=周长为L的三角形的个数减去周长为L三边最大公约数为L的约数(不包含1)的三角形的个数

  所以周长为L并且三边公约数为1的三角形的个数=周长为L的三角形的个数减去周长为L的约数(不包含L)三边公约数为1的三角形的个数。

  那么现在问题就好办了,将N的约数从小到大排序,从小到大开始周长为prime[i]公约数不为1的三角形的个数,后面的计算会用到前面的计算的,也就是代码里面GetValue所做的事情。

  整道题的时间复杂度不大, 只与N的约数的个数相关。

#include <iostream>
#include <cstdio>
#include <math.h>
#include <stdlib.h>
using namespace std;
#define mod 1000000007
int a[50];
long long yueshu[1000];
long long value[1000];
int nyueshu;long long GetNumber(long long N)//N可构成的三角形的个数
{if(N<3){return 0;}long long result=0;long long n=N/4;if(N%2==1){if(n%2==1){result=(1+(n-1)/2)*(n-1)/2+(n+1)/2;}else{result=(1+n/2)*n/2;}}else{if(n%2==1){result=(1+n/2)*(n/2);}else{result=(1+(n-1)/2)*((n-1)/2)+n/2;}}long long temp=N-N/4*3-3;long long k=temp/3+1;if(temp<0){return result;}long long t1;long long t2;if(temp%2==0){t1=temp/2;t2=t1-2;}else{t1=temp/2;t2=t1-1;}if(k%2==1){result=result+(t1+t1-k/2*3)*(k/2+1)/2+(t2+t2-3*(k/2-1))*(k/2)/2+k;}else{result=result+(t1+t1-3*(k/2-1))*(k/2)/2+(t2+t2-3*(k/2-1))*(k/2)/2+k;}return result;
}long long MOD(int N)
{int i;long long result=1;int n=0;while(N>0){n++;a[n]=N%2;N/=2;}for(i=n;i>=1;i--){result=(result*result)%mod;if(a[i]==1){result=(result*2)%mod;}}return result;
}int cmp(const void *arg1,const void* arg2)
{long long *t1=(long long*)arg1;long long *t2=(long long*)arg2;if(*t1<*t2){return -1;}else{return 1;}
}void GetYueshu(int N)
{nyueshu=0;int n=(int)sqrt((double)N);int i;for(i=1;i<=n;i++){if(N%i==0){if(N==i*i){nyueshu++;yueshu[nyueshu]=i;}else{nyueshu++;yueshu[nyueshu]=i;nyueshu++;yueshu[nyueshu]=N/i;}}}qsort(yueshu+1,nyueshu,sizeof(yueshu[0]),cmp);
}void GetValue()
{int i;int j;for(i=1;i<=nyueshu;i++){value[i]=GetNumber(yueshu[i]);}for(i=1;i<=nyueshu;i++){for(j=1;j<i;j++){if(yueshu[i]%yueshu[j]==0){value[i]-=value[j];}}value[i]=value[i]%mod;}
}long long Calculate(int N)
{GetYueshu(N);GetValue();long long result=0;int i;for(i=1;i<=nyueshu;i++){result=(result+value[i]*MOD(N/yueshu[i]-1))%mod;}return result;
} int main()
{int N;int t=1;while(cin>>N){printf("Case %d: %lld\n",t++,Calculate(N));}return 0;
}

转载于:https://www.cnblogs.com/wanggeEzio/p/6748890.html

hdoj4466题解相关推荐

  1. [JS][dfs]题解 | #迷宫问题#

    题解 | #迷宫问题# 题目链接 迷宫问题 题目描述 定义一个二维数组 N*M ,如 5 × 5 数组下所示: int maze[5][5] = { 0, 1, 0, 0, 0, 0, 1, 1, 1 ...

  2. [JS][dp]题解 | #打家劫舍(一)#

    题解 | #打家劫舍(一)# 题目链接 打家劫舍(一) 题目描述 描述 你是一个经验丰富的小偷,准备偷沿街的一排房间,每个房间都存有一定的现金,为了防止被发现,你不能偷相邻的两家,即,如果偷了第一家, ...

  3. [JS]题解 | #魔法数字#

    题解 | #魔法数字# 题目链接 魔法数字 题目描述 牛妹给牛牛写了一个数字n,然后又给自己写了一个数字m,她希望牛牛能执行最少的操作将他的数字转化成自己的. 操作共有三种,如下: 在当前数字的基础上 ...

  4. [JS]题解 | #岛屿数量#

    题解 | #岛屿数量# 题目链接 岛屿数量 题目描述 时间限制:1秒 空间限制:256M 描述 给一个01矩阵,1代表是陆地,0代表海洋, 如果两个1相邻,那么这两个1属于同一个岛.我们只考虑上下左右 ...

  5. [JS] 题解:提取不重复的整数

    题解:提取不重复的整数 https://www.nowcoder.com/practice/253986e66d114d378ae8de2e6c4577c1 时间限制:1秒 空间限制:32M 描述 输 ...

  6. 洛谷-题解 P2672 【推销员】

    独门思路!链表加优先队列! 这题一望,贪心是跑不掉了,但是我贪心并不好,所以想到了一个复杂一些但思路更保稳的做法 思路: 1 因为是离线操作,所以我们可以倒着求,先求x=n的情况,因为那样直接就知道了 ...

  7. [洛谷1383]高级打字机 题解

    题解 这道题一看就珂以用主席树啊 这是一道神奇的题目,那么我们先敲一个主席树,然后维护一个数组len,表示下一次应该在len + 1插入, 之后对于T操作,在上一个版本的len + 1上直接执行插入 ...

  8. luogu P1549 棋盘问题(2) 题解

    luogu P1549 棋盘问题(2) 题解 题目描述 在\(N * N\)的棋盘上\((1≤N≤10)\),填入\(1,2,-,N^2\)共\(N^2\)个数,使得任意两个相邻的数之和为素数. 例如 ...

  9. 【题解搬运】PAT_L1-009 N个数求和

    从我原来的博客上搬运.原先blog作废. (伪)水题+1,旨在继续摸清这个blog(囧 题目 就是求N个数字的和.麻烦的是,这些数字是以有理数"分子/分母"的形式给出的,你输出的和 ...

最新文章

  1. Python脚本文件和函数的基本运用
  2. git查看改变的方法
  3. The Property System
  4. apache ignite_从In Memory Data Grid,Apache Ignite快速入门
  5. php 商品展示html,HTML5和CSS3实现3D展示商品信息的代码
  6. freemarker java类_在freemarker使用java类方法
  7. 异常信息_共同药业被爆:大客户异常 瞒报环保处罚信息
  8. linux中用tailf实时观看tomcat日志
  9. C++加速代码(DAY 39)
  10. Android竖屏视频录制
  11. 「笔耕不辍」MQ的原理以及持久化
  12. jvm调优二:jvm内存模型剖析和参数设置
  13. 做了5年软件测试,对游戏UI自动化测试的一些理解和认识
  14. python如何使用geotools_ArcGIS工具之ET GeoWizards、GeoTools、GeoTools
  15. MySQL 表的建立与多表联结查询
  16. 点击图片实现大图预览
  17. 南邮操作与系统期末复习重点及习题汇总
  18. vue项目开发 实现自定义Transfer穿梭框效果(结合el-tree)
  19. 基于SSM实现的汽车租赁系统|汽车出租
  20. WakeData惟客数据如何赋能房企数字化经营?

热门文章

  1. 访问受限msn space 空间的又一个方法
  2. [echarts] 图表自适应宽高大小
  3. 转帖 FreeTextBox 工具条
  4. 国内著名期货专家郭晖:索罗斯筹划做空中国(我一直怀疑这次做空)
  5. CentOS 代理 proxy设置方法
  6. cic matlab,Matlab中CIC滤波器的应用
  7. Win11通过注册表修改文件默认打开方式
  8. opencv 图像识别
  9. rdworksv8教学说明书_RDWorksv8软件下载
  10. 连续信号希尔伯特变换