容斥原理1001 HDU 2841

来源:互联网 发布:js跳转指定页面 编辑:程序博客网 时间:2024/06/01 10:43

题意:
有n*n的格子,问你从(0,0)能看到多少个点
从x点-y点上没有其他点就代表从x能看到y点
思路:
就是求gcd(x,y)==1的对数
遍历x,然后通过寻找与gcd(i,y)!=1的对数来得到答案
gcd(i,y)!=1 y<=n
对i进行素因子分解
i=p1^e1 * p2^e2 * p3^e3 * … pk^ek
Ans+=m/p1+m/p2+…m/pk-m/(p1*p2)-m/(p1*p3)….+m/(p1*p2*p3)
奇加偶减
pi必须是互异的质因子,如果不是互异的假设2和2*2,因为事件2完全包含事件2*2

#include<stdio.h>#include<string.h>#include<iostream>#include<algorithm>#include<math.h>#include<queue>#include<stack>#include<string>#include<vector>#include<map>#include<set>using namespace std;#define lowbit(x) (x&(-x))typedef long long LL;const int maxn = 1000005;const int inf=(1<<28)-1;int Fac[50];LL dfs(int pos,LL now,int step,int m){    LL Ans=0;    if(pos==Fac[0]+1)    {        if(now==1) return 0;        if(step&1)            Ans+=m/now;        else            Ans-=m/now;        return Ans;    }    Ans+=dfs(pos+1,now,step,m);    Ans+=dfs(pos+1,now*Fac[pos],step+1,m);    return Ans;}LL Solve(int x,int m){    Fac[0]=0;    for(int i=2;i*i<=x;++i)    if(x%i==0)    {        Fac[++Fac[0]]=i;        while(x%i==0)        {                       x/=i;        }    }    if(x>1) Fac[++Fac[0]]=x;    return dfs(1,1,0,m);}int main(){    int T;    scanf("%d",&T);    while(T--)    {        int n,m;        scanf("%d%d",&n,&m);        if(n>m) swap(n,m);        LL Ans=m;        for(int i=2;i<=n;++i)            Ans+=m-Solve(i,m);        printf("%lld\n",Ans);    }    return 0;} 
0 0