原文链接

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.

InputThe 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)OutputFor 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的矩阵有点,左下角的点为(1,1),右上角的点(n,m),(其实转回来也是没影响的即m*n),一个人站在(0,0)看这些点,在一条直线的视线上,它只能看到最前面的那个点,后面的点将会被档住他看不到,问你,这个人一共能看到多少个点。

这个问题只要画一下图不难发现,如果一个点(x,y),x和y有非1的公约数z,那么他们其实可以一起缩小为(x/z,y/z),试着把这两个点和(0,0)连线,发现他们其实是同一条直线,而(x/z,y/z)

在前面,所以其实(x,y)被挡住了看不到的,这启发了我们,如果我们找到了x和y的最大公约数g,那么(x/g,y/g)一定是这条直线上最前面的点,没有其他店能挡住他,他一定能被看到,而他后面的点都看不到,那么(x/g,y/g)满足的性质就是,这两个数字互质

从而得到一个结论,两个数字(x,y)如果两数互质,则可以被看到,如果不互质,则看不到,所以我们就是要找出所有的二元组(x,y)使他们互质

我们可以固定一个数字,用一个数来循环。例如矩阵为n*m,我们固定m,用n来循环,即1与[1,m]里面多少个数互质,2与[1,m]里面多少个数互质,3与[1,m]里面多少个数互质……n与[1,m]里面多少个数互质,把这些结果全部累加起来即可

所以问题的最后变为了,给定一个数字x,怎么找出它和1到y里面有多少个数互质呢?

两个数字互质,其实就是它们没有公共的质因子,反过来两个数字有公共的质因子则一定不互质,那么我们可以求反面,x与1到y里面多少个数字不互质,然后用y减去即可

在这里我们就用到了容斥原理:先找到有多少个数和x有1个公共的质因子,然后加上;再找到有多少个数与x有2个公共的质因子,然后减去;再找到有多少个数有多少个数与x有3个公共的质因子,然后加上……最后得到的个数,就是有多少个数与x不互质

因为容斥原理一个最基本的准则就是——

要计算几个集合并集的大小,我们要先将所有单个集合的大小计算出来,然后减去所有两个集合相交的部分,再加回所有三个集合相交的部分,再减去所有四个集合相交的部分,依此类推,一直计算到所有集合相交的部分。(奇数加,偶数减)

AC代码:

 1 #include <cstdio>
2 #include <cstring>
3 #include <cmath>
4 #include <vector>
5 #include <queue>
6 #include <algorithm>
7 using namespace std;
8 #define MAX 100010
9
10 bool p[MAX];
11 vector<int>fac[MAX];//保存每个数字带有的质因子
12
13 void init()
14 {
15 for(int i=0; i<MAX; i++) fac[i].clear();
16 memset(p,false,sizeof(p));
17 for(int i=2; i<MAX; i++)
18 if(!p[i]) //i是质因子
19 {
20 fac[i].push_back(i);
21 for(int j=i+i; j<MAX; j+=i)
22 {
23 p[j]=true; //不是质因子
24 fac[j].push_back(i); //j这个数字都含有质因子i
25 }
26 }
27 }
28
29 int cal(int n , int m)
30 {
31 int size=(int)fac[n].size(); //得到n这个数字有多少个质因子
32 int maxs=1<<size; //从中选一些质因子,就是生成子集,子集最多个数
33 int Count=0; //记录n与1到m这m个数中多少个数互质
34 for(int s=1; s<maxs; s++) //枚举子集,不能有空集所以从1开始
35 {
36 int k=0 , num=0 , pro=1;
37 for(int i=0; i<size; i++)
38 if(s&(1<<i)) //有第i个质因子
39 {
40 num++; //计数
41 pro *= fac[n][i]; //乘上这个质因子
42 }
43 if( num&1 ) //选出了奇数个质因子,按照容斥原理加上
44 Count += m/pro;
45 else //选出了偶数个质因子,按照容斥原理减去
46 Count -= m/pro;
47 }
48 return m-Count;
49 }
50
51 int main()
52 {
53 int T,H,W;
54 init();//找出每个数字带有的质因子
55 scanf("%d",&T);
56 while(T--)
57 {
58 scanf("%d%d",&H,&W);
59 if(W>H) //交换可令循环次数减少
60 { H=H^W; W=H^W; H=H^W;}
61 long long ans=H;
62 for(int w=2; w<=W; w++)
63 ans += cal(w,H);
64 printf("%I64d\n",ans); //注意输出格式不能用%lld
65 }
66 return 0;
67 }

hdu 2841 Visible Trees(容斥)的更多相关文章

  1. C - Visible Trees HDU - 2841 -莫比乌斯函数-容斥

    C - Visible Trees HDU - 2841 思路 :被挡住的那些点(x , y)肯定是 x 与 y不互质.能够由其他坐标的倍数表示,所以就转化成了求那些点 x,y互质 也就是在 1 - ...

  2. HDU 2841 Visible Trees(容斥定理)

    Visible Trees Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) To ...

  3. HDU 2841 Visible Trees(容斥)题解

    题意:有一块(1,1)到(m,n)的地,从(0,0)看能看到几块(如果两块地到看的地方三点一线,后面的地都看不到). 思路:一开始是想不到容斥...后来发现被遮住的地都有一个特点,若(a,b)有gcd ...

  4. HDU 2841 Visible Trees 数论+容斥原理

    H - Visible Trees Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u S ...

  5. HDU 2841 Visible Trees(数论)

    标题效果:给你个m*n方格,广场格从(1,1)开始. 在树中的每个点,然后让你(0,0)点往下看,问:你能看到几棵树. 解题思路:假设你的视线被后面的树和挡住的话以后在这条线上的树你是都看不见的啊.挡 ...

  6. hdu 2841 Visible Trees 容斥原理

    Visible Trees Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Pr ...

  7. HDU 2841 Visible Trees(莫比乌斯反演)

    题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=2841 题意:给n*m的矩阵(从(1,1)开始编号)格子,每个格子有一棵树,人站在(0,0)的位置,求可 ...

  8. hdu 2841 Visible Trees

    /** 大意: 求[1,m], [1,n] 之间有多少个数互素...做了 1695 ,,这题就so easy 了 **/ #include <iostream> #include < ...

  9. HDU 5297 Y sequence 容斥 迭代

    Y sequence 题目连接: http://acm.hdu.edu.cn/showproblem.php?pid=5297 Description Yellowstar likes integer ...

随机推荐

  1. docker里运行docker命令

    一.概述 现有环境的jenkins是在docker里面运行的,需要执行docker相关命令才行. 关于基于docker搭建jenkins,请参考链接: https://www.cnblogs.com/ ...

  2. 剑指 Offer 33. 二叉搜索树的后序遍历序列 + 根据二叉树的后序遍历序列判断对应的二叉树是否存在

    剑指 Offer 33. 二叉搜索树的后序遍历序列 Offer_33 题目详情 题解分析 本题需要注意的是,这是基于一颗二叉排序树的题目,根据排序二叉树的定义,中序遍历序列就是数据从小到大的排序序列. ...

  3. POJ-1860(最短路问题,Bellman-Ford算法判正圈)

    Currency Exchange POJ-1860 这题其实是最短路问题的变形,但是这里不用求解最短路,而是求解路径中是否存在正圈.如果存在正圈则说明兑换后的货币可以一直增加,否则不能实现通过货币转 ...

  4. web图像化服务管理工具

    在 CentOS 8 中安装 Cockpit Web 控制台 Cockpit 是红帽开发的网页版图像化服务管理工具,优点是无需中间层,且可以管理多种服务. 根据其项目主站描述,Cockpit 有如下特 ...

  5. 追洞小组 | 实战CVE-2020-7471漏洞

    出品|MS08067实验室(www.ms08067.com) 本文作者:守拙(Ms08067实验室追洞小组成员) 一.漏洞名称: 通过StringAgg(分隔符)的潜在SQL注入漏洞 二.漏洞编号: ...

  6. 安装VMTools失败的三类解决方法(Windows、Linux、MacOs)

    前言 写这篇笔记的原因,是前几天在虚拟机 Vmware 中重新安装了几个操作系统,突然发现 VMTools 这个工具成了一个特殊的问题,以前还没有发现,因为通常它就给你自动安装了.但是大多数时候也是需 ...

  7. android分析之Binder 01

    终于还是得写一篇关于Binder的文章了.从最初接触Android到花大把时间研究Android源码,Binder一直是分析道路的拦路虎.看了几本最流行的Android源码分析书籍,每次基本上都不能把 ...

  8. MySQL入门(5)——运算符

    MySQL入门(5)--运算符 算术运算符 MySQL支持的算数运算符包括加.减.乘.除.求余. 符号 作用 + 加法运算 - 减法运算 * 乘法运算 / 除法运算 % 求余运算 DIV 除法运算,返 ...

  9. 2019 GDUT Rating Contest I : Problem G. Back and Forth

    题面: G. Back and Forth Input file: standard input Output file: standard output Time limit: 1 second Mem ...

  10. css盒布局-省份选择盘的实现

    1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="U ...