1. 程式人生 > 實用技巧 >Mathematically Hard LightOJ - 1007(尤拉函式打表)

Mathematically Hard LightOJ - 1007(尤拉函式打表)

題目連結

題意:給定一個區間[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]); } }