Visible Trees HDU2841(容斥定理的简单扩展)

本文介绍了一种解决可视树问题的方法。该问题设定为在一矩形网格中,每个格子都有一棵树,从起点(0,0)观察者能看到多少棵树。同一直线上的树仅最接近观察者的可见。通过数学方法和编程实现,文章详细阐述了解决方案。

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

                          Visible Trees

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
题目大意:在一个n*m的方格中一个人站在(0,0),每个方格都有树,求他能看到多少颗树,在同一条直线上只能看到离他最近的一棵。

题目分析:第一列的所有树都能看到,因为没有任何阻挡,从第二列开始,因为列数是确定的,所有与列互质的数,即横坐标,可以看到。然后依次类推,直到最后一列。

#include<cstdio>
#include<iostream>
#include<cstring>
#include<vector>
using namespace std;
const int mx=1e5+5;

vector<int>x[mx];
bool visited[mx];
void getPrimeFactor()///预处理1~mx内数的素因子,并存储起来,很巧妙
{
    memset(visited,true,sizeof(visited));
    for(int i=2;i<mx;i++)
        if(visited[i])
    {
        for(int j=i;j<mx;j+=i)
        {
            visited[j]=false;
            x[j].push_back(i);
        }
    }
}
int solve(int a,int p)///求区间[1,a]中与p互质的个数
{
    int sum=0;
    for(int i=1;i<(1<<x[p].size());i++)
    {
        int cnt=0,val=1;
        for(int j=0;j<x[p].size();j++)
            if(i&(1<<j))
        {
            cnt++;
            val*=x[p][j];
        }
        if(cnt&1)
            sum+=a/val;
        else
            sum-=a/val;
    }
    return a-sum;
}
int main()
{
    getPrimeFactor();
    int t;
    int a,b;
    cin>>t;
    while(t--)
    {
        scanf("%d%d",&a,&b);
        long long ans=a;///第一列所有的元素的都满足
        for(int i=2;i<=b;i++)///从第二列到到第b列满足与i互质的满足
        {
            ans+=solve(a,i);
        }
        cout<<ans<<endl;
    }
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值