HDOJ 2841 Visible Trees (容斥原理)

来源:互联网 发布:笔记本电脑推荐知乎 编辑:程序博客网 时间:2024/05/22 16:41

Visible Trees

Time Limit: 2000/1000 MS(Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 3068    Accepted Submission(s): 1355

Problem Description

There are many trees forming am * 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 thetree nearest to him.

 

 

Input

The first line contains oneinteger t, represents the number of test cases. Then there are multiple testcases. For each test case there is one line containing two integers m and n(1 ≤m, n ≤ 100000)

 

 

Output

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

 

 

Sample Input

2

1 1

2 3

 

 

Sample Output

1

5



由于人站在(0,0)处,故如果有一棵树(X,Y)被另一棵树(x,y)挡住,必有X / x = Y / y,即X,Y必有公约数,因此对于任意一点(A,B),只要A,B有公约数,则一定看不到,反之,A,B互质则一定可以看到,因此问题转化为求图中的互质点对。

分析至此就可以想到用容斥定理解决,求1~n 与 1~m 中的数有多少对互质,故可以固定 i (I属于n),1~m 循环求互质数个数,然后扫一遍1~n即可


#include <bits/stdc++.h>using namespace std;#define mst(a,b) memset((a),(b),sizeof(a))#define f(i,a,b) for(ll i=(a);i<(b);++i)const int maxn = 100005;const int mod = 200907;#define ll long long#define rush() int T;scanf("%d",&T);while(T--)int prime[40];int m;void getprime(int n){    mst(prime,0);    m=0;    for(int i=2;i*i<=n;i++)    {        if(n&&n%i==0)        {            prime[m++]=i;            while(n&&n%i==0)                n/=i;        }    }    if(n>1)        prime[m++]=n;}int solve(int num){    int ans=0,temp,flag;    for(int i=1;i<(1<<m);i++)    {        temp=1;        flag=0;        for(int j=0;j<m;j++)        {            if(i&(1<<j))            {                flag++;                temp*=prime[j];            }        }        if(flag&1)            ans+=num/temp;        else ans-=num/temp;    }    return ans;}int main(){    int a,b;    int Min,Max;       //用以时间优化    ll ans;    rush()    {        ans=0;        scanf("%d%d",&a,&b);        Min=min(a,b);        Max=max(a,b);        for(int i=1;i<=Min;i++)        {            getprime(i);            ans+=(Max-solve(Max));        }        printf("%I64d\n",ans);    }    return 0;}

0 0
原创粉丝点击