Codeforces Round #226 (Div. 2) C 數論
阿新 • • 發佈:2019-02-03
CF機子真心強大啊,這樣才跑了600ms,給了你n個數的序列,然後m次詢問,每次詢問求出序列中每個數是 區間[a,b]內的 幾個素數的倍數統計一下,然後對於個數求和,看了題目下面的hint很易懂,然後看到a,b的範圍有些大哈,2*10^9,不知道怎麼處理,但是後來發現,序列中的數 最大為10^7,所以就算a,b,再大也無所謂的,大於序列中的最大數的部分的素數,序列中不會有任何數 是它倍數的,然後就是對10^7以內的 素數進行預處理,同時把序列中的數統計一下個數,在預處理素數的同時 會有一個篩選祛除 該素數倍數的過程,就在這裡判斷一下該素數的倍數是否在序列中,若在就加上該數的個數,最後求一下字首和,然後 答案就是 sum[b] - sum[a - 1]了,
在篩選素數的時候 第二個for迴圈一般都是 從2*i,開始的,但是 不保證序列中沒有素數哈,比如說第一個案例,序列中有5,那麼5是5的倍數,如果第二層迴圈從2*i開始就會漏掉一部分,這裡習慣性的寫法,讓我卡了一會,因為 那裡除錯不太好弄,
int n; int nnum[10000000 + 55]; bool isprime[10000000 + 55]; int prime[10000000 + 55]; int k; void get_prime() { memset(isprime,false,sizeof(isprime)); for(int i=2;i<10000005 ;i++) { if(!isprime[i]) for(int j=i /*2 * i*/;j<10000005;j+=i) { isprime[j]=true; if(nnum[j])prime[i] += nnum[j]; } } //for(int i=2;i<1000005;i++) // if(!isprime[i]) // prime[k++]=i; for(int i=1;i<10000005;i++) prime[i] += prime[i - 1]; } void init() { memset(prime,0,sizeof(prime)); memset(nnum,0,sizeof(nnum)); } bool input() { while(cin>>n) { for(int i=0;i<n;i++) { int x; scanf("%d",&x); nnum[x]++; } return false; } return true; } void cal() { get_prime(); int m; scanf("%d",&m); while(m--) { int a,b; scanf("%d %d",&a,&b); a = a>10000000?10000000:a; b = b>10000000?10000000:b; printf("%d\n",prime[b] - prime[a - 1]); } } void output() { } int main() { while(true) { init(); if(input())return 0; cal(); output(); } return 0; }