luogu \ # 2522 Problem b (모 비 우 스 재연) (HAOI 2011)

3837 단어 수학.
수학
제 시 된 n 개 질문 에 대해 매번 몇 개의 수 대 (x, y) 를 구 할 때마다 a ≤ x ≤ b, c ≤ y ≤ d 를 만족 시 키 고 gcd (x, y) = k, gcd (x, y) 함 수 는 x 와 y 의 최대 공약수 이다.a,b,c,d,k<=50000
g (a, b, c, d) 를 제목 으로 요구 하고 f (m, n) 를 만족 시 키 기 위해 1 ≤ x ≤ m, 1 ≤ y ≤ n, 그리고 gcd (x, y) = k 의 수 대 개 수 를 기록 하고 F (m, n) 를 만족 시 키 기 위해 1 ≤ x ≤ m, 1 ≤ y ≤ n, 그리고 gcd (x, y)% k = 0 의 수 대 개 수 를 기록한다.우선 g (a, b, c, d) = f (b, d) - f (a - 1, d) - f (b, c - 1) + f (a - 1, c - 1), f (n, m) 와 F (n, m) 는 모 비 우 스 의 반 연 을 만족 시 키 는 것 을 발견 하기 어렵 지 않다.분명히 F (n, m) = [n / k] * 8727 ° [m / k] 는 f (n, m) = > min (n / k, m / k) i = 1F (n / i, m / i) * 8727 ° 가 있다.μ(i) 그러나 이렇게 되면 복잡 도 는 O (n2) 이 고 요 구 를 만족 시 키 지 못 한다. n / i 는 n √ 가지 수치 만 있다 는 것 을 알 아차 리 지 못 한다. 우 리 는 미리 처리한다.μ(i) 접두사
#include
#include
#include
#include
#define N 50050
using namespace std;
typedef long long ll;
int u[N],vis[N],p[N],top=0,t,a,b,c,d,k;
ll ans;
ll solve(int n,int m)
{
    n/=k,m/=k;
    ll ret=0,last=0;
    if (n>m) swap(n,m);
    for (int i=1;i<=n;i=last+1)
    {
        last=min(n/(n/i),m/(m/i));
        ret+=(ll)(n/i)*(m/i)*(u[last]-u[i-1]);
    }
    return ret;
}
int main()
{
    scanf("%d",&t),memset(vis,0,sizeof(vis)),u[1]=1;
    for (int i=2;i<=N-50;i++)
    {
        if (!vis[i]) {p[++top]=i,u[i]=-1;}
        for (int j=1;j<=top&&i*p[j]<=N-50;j++)
        {
            vis[i*p[j]]=1;
            if (i%p[j]) u[i*p[j]]=u[i]*u[p[j]];else break;
        }
    }
    for (int i=2;i<=N-50;i++) u[i]+=u[i-1];
    while (t--)
    {
        scanf("%d%d%d%d%d",&a,&b,&c,&d,&k),ans=solve(b,d)-solve(a-1,d)-solve(c-1,b)+solve(a-1,c-1);
        printf("%lld
"
,ans); } }

좋은 웹페이지 즐겨찾기