hdu2841 Visible Trees(容斥原理)

来源:互联网 发布:2017年播的网络腐剧 编辑:程序博客网 时间:2024/05/15 18:58


http://acm.hdu.edu.cn/showproblem.php?pid=2841

题意:有一个n*m的格点矩形,除坐标轴上都有格点,求原点可以看见的格点个数。


思路:刚开始以为是法雷级数,咋一看不是正方形。这题和hdu1695有异曲同工之妙,主要说下自己理解的欧拉与容斥的区别:

计算集合之间互质的数对时,欧拉是1~n-1型,容斥是区间型。

打个比方,两个集合[1,b],[1,d],d>b。

在[b+1,d]区间内只能用容斥算,欧拉不行;

[1,b]中就要区分(x,y)和(y,x)是否为同一数对,如果是同一数对,按欧拉(数量少)算;否则按容斥(数量多)算。

小的匹配大的可以节省很多时间,这就是全容斥原理的好处。

知道了这些就秒杀了。


顺便说下感觉还是队列比dfs好用,改dfs一直是我的痛处。。


#include <stdio.h>#include <algorithm>#include <string.h>using namespace std;typedef long long ll;const int N = 100010;ll num[N], cnt = 0;void euler(ll n)//求出所有质因子{    cnt = 0;    for(int i = 2; i*i <= n; i++)    {        if(n%i == 0)        {            num[cnt++] = i;//保存所有质因子            while(n%i == 0)                n /= i;//彻底消除当前素因子        }    }    if(n > 1) num[cnt++] = n;}ll exclusion(ll m)//容斥,求出1~m内与n不互质的数的数目{    ll que[1005], ans;//保存所有质因子的排列组合    int top = 0, t;    que[top++] = -1;    ans = 0;    for(int i = 0; i < cnt; i++)//遍历所有质因子    {        t = top;        for(int j = 0; j < t; j++)        {            que[top++] = que[j]*(-1)*num[i];        }    }    for(int i = 1; i < top; i++)        ans+=(m/que[i]);    return ans;}int main(){   // freopen("in.txt", "r", stdin);    int t;    ll a, b, ans;    scanf("%d", &t);    while(t--)    {        cnt = 0;        ans = 0;        scanf("%lld%lld", &a, &b);        if(a > b) swap(a, b);//确定a是小的        for(int i = 1; i <= a; i++)//小的遍历大的,节省时间        {            euler(i);            ans+=(b-exclusion(b));        }        printf("%lld\n",ans);    }    return 0;}


0 0
原创粉丝点击