Visible Trees HDU - 2841

本文解析了HDU-2841 Visible Trees问题,介绍了如何通过计算互质数来确定在特定网格中可见的树木数量。采用容斥原理,通过遍历并计算满足条件的格子来得出最终答案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


Visible Trees HDU - 2841  


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.

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)

For each test case output one line represents the number of trees Farmer Sherlock can see.

Input

2
1 1
2 3

Output

1
5



题意: 给定一个m*n 的棋盘,起点从(1,1)开始,你站在 (0,0) 看,问能看见多少个格子里的树,同一条直线上的格子里的树只能看见一个。

思路: 开始想半天没想到用容斥怎么做,然后发现对于每个不能被看见的格子,满足gcd(a,b)!=1 ,即判断该格子所在的坐标(a,b)  看是否满足 gcd ( a,b )==1  ,如果是的就加一。

那么问题就变成了从 1~H 在1~W区间里的互质的数的个数, 数据 H,W不是很大,可以固定一个,遍历一边求解,那么这个题就跟上个题是一样的了。



#pragma comment(linker, "/STACK:1024000000,1024000000")
//#include <bits/stdc++.h>
#include<string>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<queue>
#include<stack>
#include<vector>
#include<algorithm>
#define maxn 100100
#define INF 0x3f3f3f3f
#define eps 1e-8
#define MOD 1000000007
#define ll long long
using namespace std;


ll Q[maxn],fac[maxn];
ll num;
void Divide(ll n)
{
    num=0;
    for(ll i=2;i*i<=n;i++)
    {
        if(n%i==0)
        {
            while(n%i==0)
                n/=i;
            fac[num++]=i;
        }
    }
    if(n!=1) fac[num++]=n;
}
ll solve(ll n)
{
    ll k,t,ans;
    t=ans=0;
    Q[t++]=-1;
    for(ll i=0;i<num;i++)
    {
        k=t;
        for(ll j=0;j<k;j++)
            Q[t++]=-1*Q[j]*fac[i];
    }
    for(ll i=1;i<t;i++)
        ans+=n/Q[i];
    return ans;
}

int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        ll H,W,ans;
        scanf("%lld%lld",&H,&W);
        if(H<W) swap(H,W);
        ans=H;
        for(ll i=2;i<=W;i++)
        {
            Divide(i);
            ans+= (H-solve(H));
        }
        printf("%lld\n",ans);
    }
    return 0;
}





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值