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