hdu 2841(容斥原理)

来源:互联网 发布:淘宝网爱康多大药房 编辑:程序博客网 时间:2024/05/16 15:02
  • 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2841

  • 题意:有一个农民,站在(0,0)点,从(1,1)点到(m,n)点每个点上有棵树,问这个农民能看到多少棵树。树被挡就看不到

  • 分析:画个图,我们就能发现一个重大问题,当两点坐标互质时就能看到树,否则就不能。这里我们就可以求解容斥原理,转而求,在1~m中有多少个数与1~n互质。我们先求不互质的个数,设i在1~m之间,进行素因子分解,则小于n能被i的素因子整除的数就不是与i互质的数,这是我们用容斥就可以求出总数。容斥原理详见链接:容斥原理

  • 代码如下:
#include <set>#include <map>#include <stack>#include <queue>#include <math.h>#include <vector>#include <string>#include <utility>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <iostream>#include <algorithm>#include <functional>using namespace std;long long ans;int n,m;struct sa{    int fen[10];    int k;}p[100000+5];bool a[100000+5];void dfs(int id,int k,int w,long long sumsum){    if(id==p[k].k+1)return;    long long temp;    for(int i=w;i<p[k].k;i++){        temp=sumsum*p[k].fen[i];        if(id&1)ans-=n/temp;        else ans+=n/temp;        dfs(id+1,k,i+1,temp);    }}//递归实现容斥原理int main(){    int t;    scanf("%d",&t);    memset(a,0,sizeof(a));    a[1]=1;    for(int i=1;i<100005;i++)    p[i].k=0;    for(int i=2;i<=100005;i++){        if(!a[i]){            for(int j=i;j<100005;j+=i){                a[j]=true;                p[j].fen[p[j].k]=i;                p[j].k++;            }        }    }//递推进行素因子分解    while(t--){        scanf("%d%d",&m,&n);        long long sum=0;        for(int i=1;i<=m;i++){            ans=n;//            cout<<p[i].k<<" ";            dfs(1,i,0,1);            sum+=ans;//            cout<<ans<<endl;        }        cout<<sum<<endl;    }    return 0;}
0 0
原创粉丝点击