HDU2841 Visible Trees(容斥原理)

题意

这道题题意就是给出第一象限的n*m个点,求出站在原点可以看见多少个点

(1<=n,m<=1^5)

题解

这个题很仪仗队差不多,不过仪仗队是正方形。

这个是长方形。。。

这题其实就是求互质的数对的对数。

我们,一个一个的枚举i,然后就是求跟i互质的数的个数。

然后这个求跟i互质的数的个数可以用容斥原理求。(我居然才知道)

其实就是求不能整除i的所有质因子的数有多少。

我们枚举i的质因子,在值域中有多少倍数,在考虑选2,3,个质因子容斥就行了。

 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdio>
 4 #include<cmath>
 5 #include<algorithm>
 6 using namespace std;
 7 const long long N=100010;
 8 long long a[N],n,m,t,ans;
 9 long long calc(long long x){
10     long long tmp=0;
11     long long tot=0;
12     for(long long i=2;i*i<=x;i++){
13         if(x%i==0)a[++tot]=i;
14         while(x%i==0)x/=i;
15     }
16     if(x>1)a[++tot]=x;
17     for(long long i=1;i<=(1<<tot)-1;i++){
18         long long cnt=0;
19         long long num=1;
20         for(long long j=1;j<=tot;j++){
21             if((1<<j-1)&i)num*=a[j],cnt++; 
22         }
23         num=m/num;
24         if(cnt&1)tmp+=num;
25         else tmp-=num;
26     }
27     return m-tmp;
28 }
29 int main(){
30     scanf("%lld",&t);
31     while(t--){
32         scanf("%lld%lld",&n,&m);
33         ans=m;
34         for(long long i=2;i<=n;i++){
35             ans+=calc(i);
36         }
37         printf("%lld\n",ans);
38     }
39     return 0;
40 }

 

posted @ 2018-09-27 20:53  Xu-daxia  阅读(134)  评论(0编辑  收藏  举报