容斥原理求一个数互质的数个数

来源:互联网 发布:河北广电网络集团地址 编辑:程序博客网 时间:2024/06/05 21:56

1160: Confusion in the Problemset

Time Limit: 1 Sec  Memory Limit: 128 MB
Submit: 107  Solved: 15
[Submit][Status][Web Board]

Description

You are in an m x n grid. You are standing in position (0, 0) and in each of the other lattice points (points with integer co-ordinates) an enemy is waiting. Now you have a ray gun that can fire up to infinity and no obstacle can stop it. Your target is to kill all the enemies. You have to find the minimum number of times you have to fire to kill all of them. For a 4 x 4 grid you have to fire 13 times. See the picture below:

Input

Input starts with an integer T (≤ 100), denoting the number of test cases.

Each case contains two integers m, n (0 ≤ m, n ≤ 109) and at least one of them will be less than or equal to 106.

Output

For each case, print the case number and the minimum number of times you have to fire to kill all the enemies.

Sample Input

24 410 10

Sample Output

Case 1: 13Case 2: 65

HINT

Source

LOJ1144



#include<stdio.h>#include<string.h>#include<algorithm>using namespace std;typedef long long lld;const int maxn=1000005;bool mk[maxn];int f[maxn];int p[maxn];int a[maxn];void Gao(){int i,j;for(i=1;i<maxn;i++){p[i]=1; mk[i]=0;}for(i=2;i<maxn;i++)if(!mk[i]){p[i]=f[i]=i;for(j=i*2;j<maxn;j+=i){f[j]=i;//记录j的最大质因子imk[j]=1;p[j]*=i;//质因子的积}}}int main(){int T;int cas=1,num,n,m;int i,j,k;int fact[15];lld ans;Gao();scanf("%d",&T);while(T--){scanf("%d%d",&n,&m);if(n>m)n^=m^=n^=m;if(n==0 ||m==0){printf("Case %d: %d\n",cas++,(m^n)!=0);continue ;}ans=2;for(i=1;i<=n;i++){if(i==p[i]){a[i]=num=0;for(j=i;j!=1;j/=f[j])//求i的质因子fact[num++]=f[j];for(j=0;j<(1<<num);j++)//容斥原理{int tmp=1,sign=1;for(k=0;k<num;k++)if(j&(1<<k)){tmp*=fact[k];sign=-sign;}a[i]+=m/tmp*sign;}}ans+=a[p[i]];}printf("Case %d: %lld\n",cas++,ans);}return 0;}

标程

#include<iostream>    #include<cstdio>    #include<cstring>    #include<algorithm>    using namespace std;    struct point    {        int x,cnt;        friend bool operator<(const point &p,const point &q){            return p.x<q.x;        }    }c[1000010];    int a[1100010],pri[1100010];    void prime()    {        memset(a,0,sizeof(a));        int i,j;        for(i=2;i*i<=1100000;i++)            if(!a[i])                for(j=i*i;j<=1100000;j+=i)                    a[j]=1;        for(i=0,j=2;j<=1100000;j++)            if(!a[j]) pri[i++]=j;    }    int cnt=0;    void dfs(int mul,int pos,int step)    {               c[cnt].cnt=step;        c[cnt++].x=mul;        int up=1000000/mul;        for(int i=pos;pri[i]<=up;i++){            dfs(mul*pri[i],i+1,step+1);        }    }    int main()    {        prime();        dfs(1,0,0);        sort(c,c+cnt);        int t;        scanf("%d",&t);        for(int k=1;k<=t;k++){            long long n,m,ans=0;            scanf("%lld%lld",&n,&m);            for(int i=0;i<cnt;i++)                if(c[i].x>min(n,m)) break;                else if(c[i].cnt&1) ans-=(n/c[i].x)*(m/c[i].x);                else ans+=(n/c[i].x)*(m/c[i].x);            if(n==0&&m==0) ans=0;            else if(n==0||m==0) ans=1;            else ans+=2;            printf("Case %d: %lld\n",k,ans);        }        return 0;    }


原创粉丝点击