pongo(csdn英雄会题解)之三元组的数量--英雄会第二届在线编程大赛·CSDN现场决赛
2013-12-30 00:23
309 查看
今天来CSDN参加了现场的决赛,我完全是为了看大神而来,开赛10分钟,cp大神就ac了,我那会还没思路,开始看错了题,后来想到了一种方法,到最后cp讲题解的时候,才发现我的想法基本和他的一样,那会我程序还没调试出来,今天切身体会到什么是高手。
下面是题目:
{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(q>=p/3+2);(条件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++代码为:
显然复杂度为sum (1/4*b/i),i=1....b,根据调和级数得,O(blogb)
下面是题目:
{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(q>=p/3+2);(条件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++代码为:
#include <stdio.h> #include <iostream> #include <string> using namespace std; class Test { public: static long Count (int a,int b){ int res=0; int *resA=new int[b-a+1]; for(int i=0;i<=b-a;++i) resA[i]=0; for(int p=1;p<=b;++p){ int d=p/4+1;//是为了下一行代码中,q的枚举初始值>=1,以减少没必要的枚举 int q=4*d-p;//保证p+q能被4整除 int p3=p/3+2;//防止while循环里面重复计算p/3+2 while(q<=b){ int tmp=p*q; if(tmp>b)break;//p*q<=b if(q>=p3){ if(tmp>=a)//p*q>=a ++resA[tmp-a]; } q+=4;//每次q增加4,保证p+q能被4整除 } } //计算Cx,2 for(int i=0;i<=b-a;++i) res+=resA[i]*(resA[i]-1); res/=2; return res; } }; //start 提示:自动阅卷起始唯一标识,请勿删除或增加。 int main() { cout<<Test::Count(1,30)<<endl; return 0; } //end //提示:自动阅卷结束唯一标识,请勿删除或增加。
显然复杂度为sum (1/4*b/i),i=1....b,根据调和级数得,O(blogb)
相关文章推荐
- pongo(csdn英雄会题解)之三元组的数量--英雄会第二届在线编程大赛·CSDN现场决赛
- 三元组数量的c#求解-英雄会第二届在线编程大赛·CSDN现场决赛
- 英雄会第二届在线编程大赛·CSDN现场决赛:三元组的数量【水题】
- 【题解】英雄会第二届在线编程大赛·CSDN现场决赛:三元组的数量
- 英雄会第二届在线编程大赛·线上初赛:AB数
- 英雄会第二届在线编程大赛·线上初赛:AB 题解
- csdn第四届在线编程大赛·线上初赛:带通配符的数
- 英雄会第四届在线编程大赛·线上初赛:带通配符的数
- 英雄会第四届在线编程大赛·线上初赛:带通配符的数
- 英雄会第四届在线编程大赛·线上初赛:带通配符的数
- 英雄会第四届编程大赛·CSDN现场决赛:比赛得分
- 【Java】 英雄会第四届在线编程大赛·线上初赛:带通配符的数 Java实现
- csdn英雄会题解之几个bing--微软必应·英雄会第三届在线编程大赛
- 英雄会第四届在线编程大赛·线上初赛:带通配符的数
- 英雄会第二届在线编程大赛圆满落幕 雅虎刷题狂人夺冠
- [转]微软联合CSDN英雄在线编程大赛
- CSDN英雄会第四届在线编程大赛·线上初赛:带通配符的数
- 微软必应·英雄会第三届在线编程大赛:几个bing
- 微软必应·英雄会第三届在线编程大赛 “几个bing” 题解
- 2·14 情人&元宵节专题:半质数的个数-c#求解-英雄会在线编程题目