洛谷 P3455 [POI2007]ZAP-Queries

题目链接

推式子

\[\sum_{i=1}^{n} \sum_{j=1}^{m} [\gcd(i,j) = d]\\ \sum_{i=1}^{\frac nd} \sum_{j=1}^{\frac md} [\gcd(i,j) = 1] \\ ----------------\\ \sum_{i=1}^{n} \sum_{j=1}^{m} [\gcd(i,j) = 1]\\ \sum_{i=1}^{n} \sum_{j=1}^{m} \sum_{p | i, p|j} \mu(p)\\ \sum_{p=1}^{n} \mu(p) \sum_{i=1}^{\frac np} \sum_{j=1}^{\frac mp} \\ \]

整除分块即可

code

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N = 1e5;
int p[N + 5], prime[N / 10], cnt;
int mu[N + 5];
ll f(int n){
    return 1ll * n;
} 
ll g(ll n, ll m){
    ll ret = 0;
    for(int l = 1, r; l <= n; l = r + 1){
        r = min(n, min(n/ (n/l), m/ (m/l)));
        ret = ret + 1ll * (mu[r] - mu[l - 1]) * f(n/l) * f(m/l);
    }
    return ret;
}
int main(){
    mu[1] = 1; p[0] = p[1] = 1;
    for(int i = 2; i <= N; ++ i){
        if(!p[i]) { prime[++ cnt] = i; mu[i] = -1; }
        for(int j = 1; j <= cnt && 1ll * prime[j] * i <= N; ++ j){
            p[prime[j] * i] = 1;
            if(i % prime[j] == 0) break; 
            mu[prime[j] * i] = -mu[i];
        }
    }
    for(int i = 1; i <= N; ++ i) mu[i] += mu[i - 1];
    int T; scanf("%d",&T);
    while(T --){
        int a,b,d; scanf("%d%d%d",&a,&b,&d);
        if(a > b) swap(a,b); a /= d; b /= d;
        printf("%lld\n",g(a, b));
    }
	return 0;
}
posted @ 2020-08-11 20:45  zhuzihan  阅读(65)  评论(0编辑  收藏  举报