【bzoj2820】YY的GCD

因为我没有BZOJ的权限号,所以我的代码只是过了样例,所以具体的细节我也不知道过没有,所以看我博客的同学要是不麻烦的话可以交一下我的代码。。

Description

神犇YY虐完数论后给傻×kAc出了一题
给定N, M,求1<=x<=N, 1<=y<=M且gcd(x, y)为质数的(x, y)有多少对
kAc这种傻×必然不会了,于是向你来请教……
多组输入

Input

第一行一个整数T 表述数据组数
接下来T行,每行两个正整数,表示N, M

Output

T行,每行一个整数表示第i组数据的结果

Sample Input

2
10 10
100 100

Sample Output

30
2791

HINT

T = 10000

N, M <= 10000000

题解:  这个题还是老套路就是还是把f(n)当成gcd(x,y)=n有多少对,那么我们就能很明显的看出F(n)的含义,就是n|gcd(x,y)的数量。

所以的话刚开始的时候我们还是应该先把方程写下来的,这样子的话我们才能根据方程进行公式推导,我们先把重要的方程写下来。。

待续

 

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=10000001;
ll mu[N],g[N];
int vis[N],prime[N];
int cnt;
void Init()
{
    memset(vis,0,sizeof(vis));
    mu[1] = 1;
    cnt = 0;
    for(int i=2; i<N; i++)
    {
        if(!vis[i])
        {
            prime[cnt++] = i;
            mu[i] = -1;
        }
        for(int j=0; j<cnt&&i*prime[j]<N; j++)
        {
            vis[i*prime[j]] = 1;
            if(i%prime[j]) mu[i*prime[j]] = -mu[i];
            else
            {
                mu[i*prime[j]] = 0;
                break;
            }
        }
    }
    g[1]=0;
    for(int i=0;i<cnt;i++)
    {
        for(int j=prime[i];j<N;j+=prime[i])
        {
            g[j]+=mu[j/prime[i]];
        }
    }
    for(int i=1;i<N;i++) g[i]+=g[i-1];
}
void slove(int n,int m)
{
    if(n>m) swap(n,m);
    ll ans=0;
    int r;
    for(int i=1;i<=n;i=r+1)
    {
        r=min(n/(n/i),m/(m/i));
        ans+=(g[r]-g[i-1])*(n/i)*(m/i);
    }
    cout<<ans<<endl;
}
int main()
{
    int t;
    int n,m;
    Init();
    scanf("%d",&t);
    for(int i=1;i<=t;i++)
    {
        scanf("%d%d",&n,&m);
        slove(n,m);
    }
}

 

posted @ 2017-02-21 16:12  Heilce  阅读(205)  评论(0编辑  收藏  举报