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.

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

题意:在m*n的方格中,每个里面有一棵树(从(1,1)到(m,n)),你在(0,0),问可以看到几棵树。

思路:这道题的话,因为当两棵树在一条直线上的时候我们看不到,所以我们判断一下一个点(x,y)能被看到的条件。就是当x,y互质的时候,这颗树才能被看见。所以问题就转换成了有多少对坐标是互质的。可以通过枚举x,看有几个y与其互质累加。这样问题就又变成,区间有几个数与某个数互质,就转变成了经典的容斥问题。

AC代码:

#include 
typedef long long ll;
const int maxx=100010;
const int inf=0x3f3f3f3f;
using namespace std;
int p[maxx];
int k;
void getp(ll n)
{
    k=0;
    for(ll i=2; i*i<=n; i++)
    {
        if(n%i==0)
        {
            p[k++]=i;
            while(n%i==0)
                n/=i;
        }
    }
    if(n>1)
        p[k++]=n;
}
ll nop(ll m)
{
    ll top=0;
    ll que[maxx];
    ll t;
    que[top++]=-1;
    for(int i=0; in)
            swap(m,n);
        ll ans=0;
        for(ll i=1; i<=m; i++)
        {
            getp(i);
            ans+=(n-nop(n));
        }
        printf("%lld\n",ans);
    }
    return 0;
}


下面再给出容斥原理的二进制版(位运算)模板:

#include 
 
using namespace std;
 
int gcd(int a,int b)
{
    return b==0?a:gcd(b,a%b);
}
int lcm(int a,int b)
{
    return a*b/gcd(a,b);
}
int solve()//求1~n与n互质的数的个数
{
    int prime[10]= {2,3,5};
    int n=30,ans,num;
    ans=0,num=3;//num是素数因子或者因子的个数,这里是素数因子
    for(int i=1; i< (1<

 

用位运算模板AC本题的代码:

#include 
 
using namespace std;
typedef long long ll;
int fac[100000];
int div(int n)
{
    int cnt=0;
    for(int i=2;i*i<=n;i++)
    {
        if(n%i==0)
        {
            fac[cnt++]=i;
            while(n%i==0) n/=i;
        }
    }
    if(n>1) fac[cnt++]=n;
    return cnt;
}
int solve(int n,int cnt)
{
    int ans=0;
    for(int i=1;i< (1<>t;
   while(t--)
   {
       int n,m;
       ll ans=0;
       cin>>n>>m;
       for(int i=1;i<=n;i++)
       {
           int cnt=div(i);
           ans+= solve(m,cnt);
       }
       cout<

 

你可能感兴趣的:(数论-容斥原理,组合数学-容斥原理)