洛谷

https://www.luogu.org/fe/problem/P4450

应该不分块也可以。

(F(n,m,d)=sumlimits_{i=1}^{n}sumlimits_{j=1}^{m}[gcd(i,j)==d])

模板题,直接套。

但是我的分块的上界忘记把n和m换过来了。

实验证明每次都要取min,不是一蹴而就的把n换到小的然后让r赋值n。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

const int MAXN=1e6;
int pri[MAXN+1];
int &pritop=pri[0];
int mu[MAXN+1];
void sieve(int n=MAXN) {
    pritop=0;
    mu[1]=1;
    for(int i=2; i<=n; i++) {
        if(!pri[i])
            pri[++pritop]=i,mu[i]=-1;
        for(int j=1; j<=pritop; j++) {
            int &p=pri[j];
            int t=i*p;
            if(t>n)
                break;
            pri[t]=1;
            if(i%p)
                mu[t]=-mu[i];
            else {
                mu[t]=0;
                break;
            }
        }
    }
    for(int i=1;i<=n;i++)
        mu[i]+=mu[i-1];
}

ll F(int n,int m,int d){
    ll res=0;
    int nm=min(n,m);
    for(int l=1,r;l<=nm;l=r+1){
        int tn=n/l;
        int tm=m/l;
        r=min(n/tn,m/tm);
        res+=1ll*(mu[r]-mu[l-1])*(tn/d)*(tm/d);
    }
    return res;
}

int main() {
#ifdef Yinku
    freopen("Yinku.in","r",stdin);
#endif // Yinku
    sieve();
    int n,m,d;
    scanf("%d%d%d
",&n,&m,&d);
    if(d==0)
        puts("0
");
    else
        printf("%lld
",F(n,m,d));
    return 0;
}
原文地址:https://www.cnblogs.com/Yinku/p/11006766.html