神炎皇【NOIP2017提高組模擬12.10】

Description

神炎皇烏利亞很喜歡數對,他想找到神奇的數對。
對於一個整數對(a,b),若滿足a+b<=n且a+b是ab的因子,則成爲神奇的數對。請問這樣的數對共有多少呢?

Input

一行一個整數n。

Output

一行一個整數表示答案,保證不超過64位整數範圍。

Sample Input

21

Sample Output

11

Data Constraint

對於20%的數據n<=1000;
對於40%的數據n<=100000;
對於60%的數據n<=10000000;
對於80%的數據n<=1000000000000;
對於100%的數據n<=100000000000000。

好久沒打,偷個懶。


解法

首先如果a+b|ab 成立。
我們設gcd(a,b)=k ,則有ak=a,bk=b .
得到k(a+b)|abd2
a+b|abk
因爲gcd(a,b)=1
所以a+b|k
題目有(a+b)k<=n.
那麼最大情況下a+b<=n
k就有ni2 種情況。
因爲gcd(a',b')=gcd(a'+b',a')
所以a′和b′又有φ(i)

線性篩出phi即可。
時間O(n) ;


代碼

#include<cstdio>
#include<algorithm>
#include<cstdlib>
#include<cstring>
#include<cmath>
#define fo(i,a,b) for(ll i=a;i<=b;i++)
#define ll long long

using namespace std;

const ll maxn=1e7+5;
ll n,phi[maxn],pri[maxn],tot,ans;
bool bz[maxn];

int main()
{
    freopen("uria.in","r",stdin);
    freopen("uria.out","w",stdout);
    scanf("%lld",&n);
    tot=sqrt(n);
    fo(i,2,tot){
        if (!bz[i]) {
            pri[++pri[0]]=i;
            phi[i]=i-1;
        }
        fo(j,1,pri[0]){
            if (i*pri[j]>tot) break;                                                            
            bz[i*pri[j]]=1;
            if(i%pri[j]==0){
                phi[i*pri[j]]=phi[i]*pri[j];
                break;
            }
            else phi[i*pri[j]]=phi[i]*(pri[j]-1);
        }
    }
    fo(i,1,tot){
        ll now=n/(i*i);
        ans+=now*phi[i];
    }
    printf("%lld\n",ans);
}

這裏寫圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章