算法_三元组的数量

{5 3 1}和{7 5 3}是2组不同的等差三元组,除了等差的性质之外,还有个奇妙的地方在于:5^2 – 3^2 – 1^2 = 7^2 – 5^2 – 3^2 = N = 15。

{19 15 11}同{7 5 3}这对三元组也存在同样的性质:19^2 – 15^2 – 11^2 = 7^2 – 5^2 – 3^2 = N = 15。

这种成对的三元组还有很多。当N = 15时,有3对,分别是{5 3 1}和{7 5 3},{5 3 1}和{19 15 11},{7 5 3}和{19 15 11}。

现给出一个区间 [a,b]求a <= N <= b 范围内,共有多少对这样的三元组。(1 <= a <= b <= 5*10^6)

例如:a = 1,b = 30,输出:4。(注:共有4对,{5 3 1}和{7 5 3},{5 3 1}和{19 15 11},{7 5 3}和{19 15 11},{34 27 20}和{12 9 6}) 

我的解法:

(1)首先为a到b的每个N值设置一个统计量,可以通过数组实现;

(2)三元组由起始值x和等差确定,即 x,x+d,x+2d,我们可以通过统计x和d来求得N,并将相应的统计量+1;

(3)最后统计对应每个N值的三元组数量,即可解题。

但是这样x和d无法枚举,继续:

由上面得(x+2d)^2-(x+d)^2-x^2=-x^2+2dx+3d^2=(3d-x)(x+d)=N;

另设p=3d-x ;   q=x+d; 那么得:p*q=N  ;   d=(p+q)/4; x=(3q-p)/4;

(注:上面在给a = 1,b = 30例子时没有给{0,3,6}与{12,9,6}这对,说明x的起始值应大于0)

所以得出下面四个限制条件:

1) p+q能被4整除;

2) 3q-p大于等于4;(条件1、2能推出3q-p能被4整除:因为3q-p+p+q=4p)

3) a=<p*q<=b

4)p,q是正整数

由上面4个限制条件我们可以通过枚举p、q来计算出相应的N值,将相应的统计量+1;

你是否会想当不同的p、q计算相同N值的时候是否会是同一个三元组?那么我们假设存在这种情况,那么:

x1=(3*q1-p1)/4  ==  x2=(3*q2-p2)/4 ;

d1=(p1+q1)/4    ==  d2=(p2+q2)/4 ;

解得p1==p2; q1==q2

所以说明只有当p、q两个值都相同时才对应同一个三元组,所以通过枚举p、q,利用上面的4个限制条件解题,转换为C++代码为:

[cpp] view
plain
copy

  1. #include <stdio.h>  
  2. #include <iostream>  
  3. #include <string>  
  4. using namespace std;  
  5. class Test {  
  6. public:  
  7.     static long Count (int   a,int   b){  
  8.         int res=0;  
  9.         int *resA=new int[b-a+1];  
  10.         for(int i=0;i<=b-a;++i)  
  11.             resA[i]=0;  
  12.         for(int p=1;p<=b;++p){  
  13.             int start=p/4+1;          
  14.             int q=4*start-p;  
  15.             int p3=p/3+2;  
  16.             while(q<=b){  
  17.                 int tmp=p*q;  
  18.                 if(tmp>b)break;  
  19.                 if(q>=p3){  
  20.                     if(tmp>=a)  
  21.                         ++resA[tmp-a];  
  22.                 }  
  23.                 q+=4;  
  24.             }  
  25.         }  
  26.         for(int i=0;i<=b-a;++i)  
  27.             res+=resA[i]*(resA[i]-1);  
  28.         res/=2;  
  29.         return res;  
  30.     }  
  31.   
  32. };  
  33. //start 提示:自动阅卷起始唯一标识,请勿删除或增加。  
  34. int main()  
  35. {     
  36.     cout<<Test::Count(1,30)<<endl;    
  37.     return 0;  
  38. }   
  39. //end //提示:自动阅卷结束唯一标识,请勿删除或增加。  

显然复杂度为sum (1/4*b/i),i=1....b,根据调和级数得,O(blogb)

时间: 2024-10-30 23:35:33

算法_三元组的数量的相关文章

用计算列实现移动加权平均算法_数据库其它

复制代码 代码如下: if OBJECT_ID('tb') is not null drop table tb if OBJECT_ID('TEMP') is not null drop table TEMP if OBJECT_ID('FUN_NOWPRICE') is not null drop FUNCTION FUN_NOWPRICE if OBJECT_ID('FUN_NOWQTY') is not null drop FUNCTION FUN_NOWQTY go create tab

CSS规则层叠时的优先级算法_经验交流

inline style  embeded style  external style  user style  inline style是丑陋的,它们穿梭在HTML文档中,与HTML元素扭成一团,给Web前端开发人员造成了许多麻烦.它们往往以这样的面目出现: <p style="color:red;">This is a paragraph.</p> embeded style比inline style绅士一些,它们也寄宿在HTML文档中,但是它们不屑于与HT

UUencode 编码,UU编码介绍、UUencode编码转换原理与算法_其它综合

UUencode编码起先用在unix网络中,先是Unix系统下将二进制的资料借由uucp邮件系统传输的一个编码程式,也是一种二进制到文字的编码.不属于MIME编码中一员.它也是定义了用可打印字符表示二进制文字一种方法,并不是一种新的编码集合.主要解决,二进制字符在传输.存储中问题.它早期在电子邮件中使用较多,最近这些年来基本上被MIME 中Base64所取代了.E-mail中一般采用UU.MIME.BINHEX三种编码标准! 我想,了解下这种编码将二进制字符转换为可打印字符实现思路!对我们以后做

asp.NET 脏字过滤算法_实用技巧

原文见http://www.jb51.net/article/20575.htm但在我这里测试的时候,RegEx要快一倍左右.但是还是不太满意,因为我们网站上脏字过滤用的相当多,对效率已经有了一些影响,经过一番思考后,自己做了一个算法.在自己的机器上测试了一下,使用原文中的脏字库,0x19c的字符串长度,1000次循环,文本查找耗时1933.47ms,RegEx用了1216.719ms,而我的算法只用了244.125ms. 更新:新增一个BitArray,用于判断某char是否在所有脏字中出现过

计算机科学中32个常用的基础算法_其它综合

奥地利符号计算研究所(Research Institute for Symbolic Computation,简称RISC)的Christoph Koutschan博士在自己的页面上发布了一篇文章,提到他做的一个调查,参与者大多数是计算机科学家,他请这些科学家投票选出最重要的算法,以下是这次调查的结果,按照英文名称字母顺序排序: 1.A* 搜索算法--图形搜索算法,从给定起点到给定终点计算出路径.其中使用了一种启发式的估算,为每个节点估算通过该节点的最佳路径,并以之为各个地点排定次序.算法以得到

asp.net TripleDES加密、解密算法_实用技巧

using System;    using System.Collections.Generic;    using System.Linq;    using System.Text;    using System.Security.Cryptography;    using System.IO;    namespace WindowsFormsApplication1    {       #region TripleDES算法           public class Clas

javascript实现playfair和hill密码算法_基础知识

时至期末,补习信息安全概论作业.恰巧遇古典密码学算法中的playfair算法和hill算法,用javascript语言实现起来是在有趣,边查百度边编码,顺便好好补习一下javascript基础. playfair Playfair密码(英文:Playfair cipher 或 Playfair square)是一种替换密码.依据一个5*5的正方形组成的密码表来编写,表中排列有25个字母.对于英语中的26个字母,去掉最常用的Z,构成密码表. 实现思路: 1,编制密码表 密钥是一个单词或词组,密码表

LINQ重写博客垃圾图片回收算法_实用技巧

思路很简单,从所有Blog Model中解析出所有文章使用的图片文件名,排除站外引用,放入一个List<string> usedPicList.再遍历图片上传文件夹,把所有图片文件的结果加入FileInfo[] fiAllPicList.然后比较usedPicList和fiAllPicList,找出所有fiAllPicList中有,而usedPicList中木有的图片,就是未被任何文章引用的垃圾图片了. 原先这个比较算法是用传统方法写的,很蛋疼,用了两重循环,一个标志位才解决问题: 复制代码

基于DoS攻击的随机数据包标记源跟踪算法_漏洞研究

作者:饥饿加菲猫(QQ120474)        iojhgfti@hotmail.com  摘要: 针对互联网上日益猖獗的拒绝服务攻击(DoS),分析了传统的随机数据包标记算法的性能缺陷,提出一种新的基于散列消息鉴别码的返回跟踪算法HPPM,通过分析其性能指标,说明该算法提高了返回跟踪DoS攻击的效率和准确性.  感谢帮过我的几个高手袁哥[nsfocus], sunwear[E.S.T] , isno[xfocus] , scz[nsfocus]  1.引言      拒绝服务攻击,简称Do