完美三元组

来源:互联网 发布:雷洋事件最新进展知不 编辑:程序博客网 时间:2024/05/29 05:11

问题:

定义完美三元组,(a,b,d),a是d的倍数,b是d的倍数且a>=b>=d>=1;

输入:

T组测试数据,第一行一个T(1<=T<=10000),之后T行每行两个整数L,R,表示三元组中a 的取值区间[L, R].
在此条件下,求满足的完美三元组的总数  ( 1<=L<=R<=100000)。

输出:

一个整数。



分析:

首先,a的值已经确定,又d是a的约数,所以d的值可以确定,又b是d的倍数且b<=a,所以b的值可以确定。
假设 a = 12.   12 的 约数为(1,2,3,4,6,12).共6个,所以d的取值共6个。

每一个d对应着1个或多个b的值。假设 d=1,那么b = 1,2 ,3,4,····12共12种取值。。d=2时,b=2,4,6···12共6种取值。。

可以发现!!因为b最大等于a,最小等于d,且b是d的倍数,又 a是d的倍数,所以每个d对应的b的个数为 a/d!!

而a/b是a的约数!!!! 所以每一个a的值能组成的完美三元数的个数=a的所有因数的和!!!!
:a = 12 时 完美三元数组的个数为  1+2+3+4+6+12=28 个。

注意:

当两个因数相同时,也就是a时平方数时,如3^2=9 只需要把3加一次,因为d=3的两次情况时重复的。。

(L ,R 的取值范围很大,如果循环枚举,一定会超时,所以打表很方便。)

#include <stdio.h>#include <math.h>#define N 100010typedef long long LL;   //typedef 作用是为一种数据类型定义一个新名字 另外再专门研究 它的用法LL dp[N];  // lang long 类型的数组void init() {     int i,j; // 此函数没有返回值  就是打表 所以用void定义(以后详细学习这个)    for( i = 1; i <= 100000 + 5; i++)        {        LL ans = 0;  // long long 型变量        for( j = 1; j <= sqrt(i); j++)       //  因数一定在sqrt(i)的两边,不需要判断所有的i。        {            if(i % j == 0)                 // 如果 i 是j的整倍数,也就是j是i的约数            {                ans = ans +j+i/j;        //所有约数的和,                if(j * j == i)          //如果i是平方数,此时                    ans -= j;          //减去一个j  避免重复。。。。!!!!            }        }        dp[i] += ans + dp[i - 1];   //dp[i]= 当前i所有约数的和加上之前所有的i所有约数的和(精髓!!!!!!)    }                              //如:L=2,R=4;  dp[4](就是dp[R]) 已经是 a = 1--4 的所有完美三元数组的个数了,但是}                                 //只需要 2--4  ,那么减去 dp[1] (就是dp[L-1])就行了!!! int main()                             {    int T, L, R;    init();    scanf("%d", &T);    while(T--)    {        scanf("%d %d", &L, &R);        printf("%lld\n", dp[R] - dp[L - 1]);    // 巧妙!!!    }    return 0;}






原创粉丝点击