Title Link: Http://codeforces.com/problemset/problem/691/F
The main topic: given n number, and then to M inquiry, each query to a p, the number of N to find how many logarithm of the product ≥p
Data range: 2≤n≤10^6, 1≤ai≤3*10^6,1≤m≤10^6, 1≤p≤3*10^6
Problem-solving ideas: When the game is more naive the idea is to put the number of N in the heavy, for each p, up to enumerate √p step, you can get the answer. And this naive idea is O (p√p), the result of T.
Then baffled, went to see the official answer. Feeling is a kind of thought that is necessary to summarize. the model of thinking is the prime number of the sieve.
When the number of sieve is enumerated to a prime PR, we take the multiple of the PR in the Max range in turn to mark. This seems violent, in fact the complexity is almost O (n) (actually O (MAX/P1+MAX/P2). MAX/PK))
Back to this topic, you can learn from the above ideas, from 1-max enumeration A, and then from the 1-MAX/A enumeration of the other half B, n number of products equal to the logarithm of i ans[i], then there is ans[a*b] + = Cnt[a]*cnt[b]; Cnt[i] Indicates how many times the number of I in N is present. Careful analysis of the complexity of the word is O (Max/1+max/2+max/3+...+max/max), in fact, this thing is close to O (Maxlogmax), this idea in dealing with some problems of number theory is also very useful. I think the point of this complexity is that he has an upper limit of Max, and the internal operation is multiplied.
Finally get ans[i] and then take a prefix and get the n number of product <p logarithm, with the total logarithm one minus to get the answer.
#include <cstdio>#include<cstdlib>#include<cstring>#include<cmath>#include<algorithm>using namespaceStd;typedefLong LongLL;Const intMAXN =3e6;intN, M, MaX;intA[MAXN +5], P[MAXN +5]; LL CNT[MAXN+5], SUM[MAXN +5];intMain () { while(~SCANF ("%d", &N)) {memset (CNT,0,sizeof(CNT)); memset (SUM,0,sizeof(sum)); for(inti =1; I <= N; i++) scanf ("%d", &a[i]), cnt[a[i]]++; scanf ("%d", &m); MaX =-(1<< -); for(inti =1; I <= m; i++) scanf ("%d", &p[i]), MaX =Max (max, p[i]); for(inti =1; I <= MaX; i++) for(intj =1; I * j <= MaX; J + +) if(I! = j) Sum[i * j] + = cnt[i] *Cnt[j]; ElseSum[i * j] + = cnt[i] * Cnt[i]-Cnt[i]; for(inti =1; I <= MaX; i++) Sum[i] + = sum[i-1]; for(inti =1; I <= m; i++) printf ("%i64d\n", (LL) n * (N-1)-Sum[p[i]-1]); }}View Code
Educational codeforces Round 14-f (codeforces 691F)