10.30 T1 小学数学

*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;
} 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章