2018京東校招筆試題-資料分析崗
阿新 • • 發佈:2019-01-02
題目大意是給出一個數字n,問a^b=c^d(1<=a、b、c、d<=n)這種式子的個數 1^2=1^1 1^1=1^2,這樣的算兩個,n<=100000.
首先分析題目,n的資料範圍肯定是不能暴力的,從其他同學的反饋也表示這題暴力只能過20%
此題的規律在於,以一個較小的數字a當基底 將 a^p 和 a^q(設為m,n)當做新的底來計算m^c=n^d(m、n<=n),才能避免重複和漏判
比如4(2^2)和8(2^3),此時需要計算2和3的最小公倍數,然後再計算在冪指數不超過n的情況下滿足4^c=8^d的式子的個數
比如從2^k開始,分別計算底為2^k和(2^(k+1)一直到2^s(2^s<=n&&s>=k+1))的式子,同時要將2^k置為已訪問過,防止重複計算(2^k<=n)
#include <iostream> #include <cstdio> #include <cmath> #include <cstring> #include <queue> #include <algorithm> #define LL long long using namespace std; const LL p = 1e9+7; LL gcd(LL a,LL b){ LL m=a,n=b,c; while(b!=0){ c=a%b; a=b; b=c; } LL sum=m*n/a; return sum; } LL mizhishu(LL n,LL k){ LL sum=1; for(LL i =0;i<k;i++){ sum*=n; } return sum; } LL n; LL ans=0; LL hash_n[101000]; int main(){ cin>>n; memset(hash_n,0,sizeof(hash_n)); if(n==1){ cout<<1<<endl; return 0; } LL k; LL k1; LL k2; LL sum; ans=0; ans+=(n*n)%p; ans%=p; //cout<<ans<<endl; for(LL i=2;i<=n;i++){ ans+=n; ans%=p; if(hash_n[i]==0){ k=1; while(mizhishu(i,k)<=n){ //cout<<mizhishu(i,k)<<endl; //ans+=2*(n/k); hash_n[mizhishu(i,k)]=1; k1 = k+1; while(k1<=n&&mizhishu(i,k1)<=n){ sum = gcd(k,k1); //cout<<"i:"<<i<<" k: "<<k<<" k1: "<<k1<<" sum:"<<sum<<endl; ans+=2*(n*k/(sum)); ans%=p; k1++; } ans%=p; k++; } } } ans%=p; cout<<ans<<endl; return 0; }