HDU2841 Visible Trees (容斥原理)

来源:互联网 发布:手机镜子下载软件 编辑:程序博客网 时间:2024/05/16 05:46

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2841

题意: 

一个人在(0,0)点,然后前面有一个m*n的格子 ,每个格子的节点上有一棵树,问这个人站在原地能看到多少棵树

如果两棵树在一条直线上那么只能看到最前面的一棵树。

分析

如果一个数的坐标为(a,b),那么坐标为(a*k,b*k)的都不能看见,如果a,b有公因子c那么我们肯定只能看到(a/c,b/c);

因此我们得出结论,能看到的树的横纵坐标一定互质。那么我们就可以把问题转化为,从[1,n]有多少个数与m里的数互质。

那么只用把[1,n]里的数都素因子分解了,然后容斥一下就搞定了。

代码如下

#include <iostream>#include <cstring>#include <cstdio>#include <vector>using namespace std;const int maxn = 100010;typedef long long LL;int Prim[maxn],num[maxn][20];void init(){    int i,j;    memset(Prim,0,sizeof(Prim));    for(i=1; i<=100000; i++) num[i][0]=0;    for(i=2; i<=100000; i++)    if(Prim[i]==0)    {        num[i][1]=i;        num[i][0]++;        for(j=i*2; j<=100000; j+=i)        {            num[j][++num[j][0]]=i;            Prim[j]=1;        }    }}LL dfs(int id,int b,int now)//求不大于b的数中,与now不互质的数的个数;{    LL ans=0;    for(int i=id;i<=num[now][0];i++)        ans+=b/num[now][i]-dfs(i+1,b/num[now][i],now);    return ans;}int main(){    int m,n,t;    cin>>t;    while(t--){        cin>>m>>n;        init();        long long sum=0;        for(int i=2;i<=m;i++)            sum+=n-dfs(1,n,i);        printf("%I64d\n",sum+n);    }    return 0;}



0 0
原创粉丝点击