Mathematically Hard LightOJ - 1007(尤拉函式打表)
阿新 • • 發佈:2020-09-16
題意:給定一個區間[m, n],假設 小於m的與m互質的數的個數為 s(m),小於m+1的與m+1互質的數的個數為 s(m+1),……,小於n的與n互質的數的個數為 s(n)。如果 m == n,輸出 a = s(m)*s(m),否則,輸出 a = s(m)*s(m) + s(m+1)*s(m+1) + …… + s(n)*s(n)。資料規模為maxv = 5 * 10^6
思路:很容易想到尤拉函式打表,雖然是水題但我也要記錄一下,因為我瘋狂wa和re,wa的原因是需要用到ull。而re的原因居然是定義的陣列太多了,太不可思議了,所以我要記錄一下,因為需要定義的陣列不能過多,所以需要用到Eratosthenes篩法,其時間複雜度是O(NlogN)。所以線性篩法都不行QAQ。
#include<stdio.h> #include<math.h> #include<string.h> #include<map> #include<algorithm> #define N 200060 #define ll long long #define ull unsigned long long using namespace std; const int maxn=5000005; ull ans[maxn]; void count(int n) //求1~maxv的所有尤拉函式 { memset(ans,0,sizeof(ans)); for(int i=2;i<n;i++){ if(!ans[i]) //第一個ans[i] == 0 的都是素數 { for(int j=i;j<n;j+=i) //素數的倍數 { if(!ans[j]) ans[j]=j; //對素數倍數賦值 ans[j]=ans[j]/i*(i-1); //求尤拉函式的值 } } }for(int i=2;i<n;i++) //求平方和 ans[i]=ans[i-1]+ans[i]*ans[i]; } int main() { int t,u=0; count(maxn); scanf("%d",&t); while(t--) { int a,b; scanf("%d%d",&a,&b); printf("Case %d: ",++u); printf("%llu\n",ans[b]-ans[a-1]); } }