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 }