http://acm.hdu.edu.cn/showproblem.php?pid=2841


有一个n*m的方格,从(1,1)開始,每一个点有一棵树,一个人站在(0,0)点,问他能看到几棵树。当(0,0)和另外的点在一条直线上时他仅仅能看到近期的一棵。


题目意在求在m*n的方格中有多少种y/x,由于两个y/x相等的点仅仅能看到一个。有多少种y/x也就是有多少 个(x,y)x与y互质。当中(1<=x<=m,1<=n<=y)。

这样就上一题类似了,求一个区间[1,m]内与i的互质的数的个数。这里1<=i<=n。先求出与i不互质的,对i分解质因子然后容斥。


#include <stdio.h>
#include <iostream>
#include <map>
#include <set>
#include <bitset>
#include <list>
#include <stack>
#include <vector>
#include <math.h>
#include <string.h>
#include <queue>
#include <string>
#include <stdlib.h>
#include <algorithm>
#define LL __int64
//#define LL long long
#define eps 1e-9
#define PI acos(-1.0)
using namespace std;
const LL INF = 1<<30;
const int maxn = 100010;

LL ans;
int n,m;
int fac[maxn];
int prime[maxn];
int facCnt;

void getPrime()
{
    bool flag[maxn];
    memset(flag,false,sizeof(flag));
    prime[0] = 0;

    for(int i = 2; i < maxn; i++)
    {
        if(flag[i] == false)
            prime[++prime[0]] = i;
        for(int j = 1; j <= prime[0]&&i*prime[j]<maxn; j++)
        {
            flag[i*prime[j]] = true;
            if(i % prime[j] == 0)
                break;
        }
    }
}

void getFac(int num)
{
    int tmp = num;
    facCnt = 0;
    for(int i = 1; i <= prime[0] && prime[i]*prime[i] <= tmp; i++)
    {
        if(tmp % prime[i] == 0)
        {
            fac[facCnt++] = prime[i];
            while(tmp%prime[i] == 0)
                tmp /= prime[i];
        }
        if(tmp == 1)
            break;
    }
    if(tmp > 1)
        fac[facCnt++] = tmp;
}

LL solve(int m)
{
    //队列数组
    int que[110];
    int l = 0;
    que[l++] = 1;

    for(int i = 0; i < facCnt; i++)
    {
        int k = l;
        for(int j = 0; j < k; j++)
            que[l++] = fac[i]*que[j]*(-1);
    }

    LL anw = 0;
    for(int i = 0; i < l; i++)
        anw += m/que[i];
    return anw;
}

int main()
{
    int test;
    scanf("%d",&test);
    getPrime();
    for(int item = 1; item <= test; item++)
    {
        scanf("%d %d",&n,&m);
        if(n > m)
            swap(n,m);
        ans = 0;
        for(int i = 1; i <= n; i++)
        {
            getFac(i);
            ans += solve(m);
        }
        printf("%I64d\n",ans);
    }
    return 0;
}