*PS:突然被小学数学弄得怀疑人生(⊙_⊙)…老师等等我ヾ(>Д<;))))…..
先科普一下
(百度百科)
整除 [zhěng chú]
若整数a除以非零整数b,商为整数,且余数[1] 为零, 我们就说a能被b整除(或说b能整除a),a为被除数,b为除数,即b|a(“|”是整除符号),读作“b整除a”或“a能被b整除”。a叫做b的倍数,b叫做a的约数(或因数)。整除属于除尽的一种特殊情况。
也就是 x%(a*b)== 0 。
这里注意有序对( a,b )是想表达(a,b)和(b,a)是不同的 并不是a < b 或者是 b < a qwq
换个思路 x/(a*b)=c , 即 x= a * b * c ;
所以求f[x]时我们可以固定 a , b 来找 c 。
发现对于一组满足条件的(a,b,c),若其中的任意两个数相同对答案的贡献为3,全都相同贡献为1,全都不同贡献为6(3!)。
因此枚举 a 来计算重复时的情况(即不同的 (a,b,c) 的数量),枚举a,b来计算互不重复时的情况。(为避免重复计算,规定a<=b<=c ,故 1<=a<=三次根下(N) , a<=b<=根号(n/a))
并且我们发现 n /(a*a)就是 1~n 中满足任意两个数相同时的(a,b,c)的数量之和,n/(a *b)-b 就是1~n中满足三个数各不相同时的数量之和(-b是去掉前面两个数重复的情况)。 所以并不需要从1 for 到 n。
代码
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
long long N,ans=0,cnt;
int main()
{
freopen("a.in","r",stdin);
freopen("a.out","w",stdout);
scanf("%lld",&N);
cnt=0;
for(long long a=1;(a*a)<=N;++a) // 两个数相同
{
cnt+=N/(a*a);
if(a*a*a<=N) --cnt,++ans; // 三个数相同
}
ans+=cnt*3;
cnt=0;
for(long long a=1;(a*a)<=N;++a)
for(long long b=a+1;(b*b*a)<=N;++b) // 互不相同
cnt+=N/(a*b)-b;
ans+=cnt*6;
printf("%lld",ans);
return 0;
}