CQOI2007 餘數之和sum。
#include <iostream>#include <cstdio>#include <cstring>#include <cmath>#include <algorithm>#include <vector>#define pii pair<int,LL>using namespace std;typedef long long LL;const int N = 10000005;int cnt = 0 , prime[N] , minumfac[N];int totnum[N] , diffnum[N] , p[N];bool isnotprime[N];// int miu[N];void init () { isnotprime[0] = isnotprime[1] = true; cnt = 0 ; // miu[1] = 1; for (int i = 2 ; i < N ; i ++) { if (!isnotprime[i]) { prime[cnt ++] = i; // miu[i] = -1; } for (int j = 0 ; j < cnt && i * prime[j] < N ; j ++) { isnotprime[i * prime[j]] = true; minumfac[i * prime[j]] = prime[j]; // if (i % prime[j] == 0) miu[i * prime[j]] = 0; // else miu[i * prime[j]] = - miu[i]; if (i % prime[j] == 0) break; } } p[1] = 0; for (int i = 2 ; i < N ; i ++) { if (!isnotprime[i]) totnum[i] = diffnum[i] = 1; else { totnum[i] = totnum[i / minumfac[i]] + 1; diffnum[i] = diffnum[i / minumfac[i]] + ((i / minumfac[i]) % minumfac[i] != 0); } if (totnum[i] == diffnum[i]) p[i] = (((totnum[i] - 1) & 1) ? -1 : 1) * totnum[i]; else if (totnum[i] - diffnum[i] == 1) p[i] = (diffnum[i] & 1) ? -1 : 1; else p[i] = 0; p[i] += p[i - 1]; }}int main () { #ifndef ONLINE_JUDGE freopen ("input.txt" , "r" , stdin); // freopen ("output.txt" , "w" , stdout); #endif int t; scanf ("%d" , &t); init (); while (t --) { int n , m ; LL ans = 0; scanf ("%d %d" , &n , &m); if (n > m) swap (n , m); /* // stage 1: // make talbe : O(n) // for every query : O(n * prime_count(n)) for (int i = 0 ; i < cnt ; i ++) { int p = prime[i]; for (int j = p ; j <= n ; j += p) { #define f(a , b , p) ((a / p) * (b / p)) ans += miu[j / p] * f(n , m , j); } } */ /* // stage 2: // make table : O(n) // for every query : O(n) for (int i = 1 ; i <= n ; i ++) { #define f(d) ((n / d) * (m / d)) ans += p[i] * f(i); } */ // stage 3: // make table : O(n) // for every query : O(sqrt (n)) for (int i = 2 , next; i <= n ; i = next) { int d1 = n / i , d2 = m / i; int next_n = n / d1 + 1 , next_m = m / d2 + 1; next = min (next_m , next_n); ans += 1LL * (p[next - 1] - p[i - 1]) * d1 * d2; } printf ("%lld\n" , ans); } return 0;}