Visible Trees(容斥原理)

本文介绍了一种计算从原点可见树木数量的方法。通过分析样例理解题目需求,即求两个范围内互质数的数量。利用质因数分解及欧拉函数原理,提供了一种高效的解决方案。

Problem Description
There are many trees forming a m * n grid, the grid starts from (1,1). Farmer Sherlock is standing at (0,0) point. He wonders how many trees he can see.

If two trees and Sherlock are in one line, Farmer Sherlock can only see the tree nearest to him.
Input
The first line contains one integer t, represents the number of test cases. Then there are multiple test cases. For each test case there is one line containing two integers m and n(1 ≤ m, n ≤ 100000)
Output
For each test case output one line represents the number of trees Farmer Sherlock can see.
Sample Input
2
1 1
2 3
Sample Output
1
5
Source
2009 Multi-University Training Contest 3 - Host by WHU

题意:主人公站在(0,0)这个点,给你一个m*n的网格,网格中的格点代表树,如果两棵树和主人公在一条线上,那他只能看到离他近的那个点。
分析:开始很懵,然后这道题我是分析样例知道他是要求[1,m]和[1,n]互质的个数有多少个,不知道别人是怎么分析的

这个题就几乎和GCD那题一样,改一点就行了

代码如下:

#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
#include<vector>a
using namespace std;
typedef long long LL;
const int N=1e5+10;
int m,n;
LL primes[10000],A[N],phi[N];
LL que[N];
LL solve(int n,int m)
{
    int i,j,cnt=0;
    for(i=2; i*i<=n; i++)
    {
        if(n%i==0)
        {
            primes[cnt++]=i;
            while(n%i==0)
                n/=i;
        }
    }
    if(n>1)
        primes[cnt++]=n;
    LL front=0,sum=0,uu;
    que[front++]=-1;;
    for(i=0; i<cnt; i++)
    {
        uu=front;
        for(j=0; j<uu; j++)
            que[front++]=que[j]*primes[i]*(-1);
    }
    for(int i=1; i<front; i++)
        sum+=m/que[i];
    return sum;
}
int main()
{
    int t;
    //freopen("E:\\in.txt","r",stdin);
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&m,&n);
        LL p,q;
        p=min(m,n);///使p为两者中的小的
        q=max(m,n);//使q为大的
        LL sum=q;
        for(int i=2; i<=p; i++)
        {
            sum+=q;
            sum-=solve(i,q);///减去[2,p]中与[1,q]中不互质的个数
        }
        printf("%lld\n",sum);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值