2017.10.2 国庆清北 D2T1 (a*b)|x

在电脑上后面仨点过不了,要用I64d,lld会炸。但是洛谷上要用lld,LINUX系统没有I64d

 1 /*
 2 求一个数对满足 (a*b)|n,也就是求三个数 a*b*c=n,那么求1~n之间的,就是a*b*c<=n了 
 3 (a,b,c)是有序的,
 4 答案= 
 5      1、a<b<c(六种排列),则总答案应为用假定的范围求出的答案 *6+
 6      2、a=b!=c时(三种排列)得到的答案 *3+
 7      3、a=b=c时(只有一种排列)的答案 *1
 8 这样枚举 第一层 a最大到 三次根号n,b最大为二次根号(n/a) 
 9 总复杂度 O(5/6根号 n) 约为 1e8 
10 */
11 
12 #include<iostream>
13 #include<cstdio>
14 #include<cstring>
15 #include<cmath>
16 #include<algorithm>
17 using namespace std;
18 
19 long long n;
20 long long ans,temp;
21 
22 int main()
23 {
24     scanf("%lld",&n);
25     //计算a<b<c的情况 
26     for(long long i=1,t;i*i<=(t=n/i);++i,++ans)    //ans++的是a=b=c的情况 
27         for(long long j=i+1;j*j<=t;++j)
28             temp+=n/(i*j)-j;    /*因为c>b,所以小于c大于b的数都可以,所以小于等于b的数要舍去,即减去b。
29                                  而且不必担心减j后减出负数,因为a<=3√n,b<=3√n,所以c>=3√n*/     
30     ans+=temp*6;    //6种排列方式,ans*6 
31     temp=0; 
32     for(long long i=1,t;(t=i*i)<=n;++i)    //计算a=b!=c的情况 
33     {
34         temp+=n/t;
35         if(t*i<=n) --temp;        //t=i*i,t*i=i*i*i,因为a=b=c的情况前边算了,所以减去 
36     }
37     ans+=temp*3;    //三种排列方式,ans*3 
38     printf("%lld",ans);
39     return 0;
40 }
View Code

 

posted @ 2017-10-10 11:49  whymhe  阅读(174)  评论(0编辑  收藏  举报