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 }