hdu 1796 How many integers can you find 容斥定理

一开始看 这里 这个文章博主写得很好。

当举容斥定理的所谓 奇数为负 偶数为正的时候。

我直接就认为是 a*b 了。实际上是lcm(a,b)。

由于博文中的因子都是互素的(素数之间)。所以lcm(a,b) = a*b。

用队列数组做的。比较简单干净点。原理就不解释了吧。容斥定理。可以看相关论文。

#include<stdio.h>
#include<string.h>

__int64 queue[100000];
int M[25];
int num2,num1;
int t;
__int64 gcd(__int64 a,__int64 b)
{
    if(a>b){t=a;a=b;b=t;}
    if(a==0){return b;}
    return gcd(b%a,a);
}
__int64 lcm(__int64 a,__int64 b)
{
    return a/gcd(a,b)*b;
}

void Init(int tot)
{
    int i,j;
    num1 = num2=1;
    queue[0] = -1;
    for(i=0;i<tot;i++)
    {
        if(M[i]==0){continue;}
        for(j=0;j<num1;j++)
        {
            if(queue[j]<0)
            {
                queue[num2++] = lcm(-queue[j],M[i]);
            }
            else
            {
                queue[num2++] = -lcm(queue[j],M[i]);
            }
        }
        num1 = num2;
    }
}
int main()
{
    __int64 n;
    int m;
    int i,j;
    __int64 count;
    while(scanf("%I64d%d",&n,&m)!=EOF)
    {
        
        count = 0;
        int tot = 0;
        for(i=0;i<m;i++)
        {
            scanf("%d",&M[tot++]);
        }
        Init(tot);
        for(i=1;i<num2;i++)
        {
            
            count += (n-1)/queue[i];
        }
        
        printf("%I64d\n",count); 
    }
}

/*
Output Limit Exceeded 多写了几个输出。
Time Limit. 数组开太小。

WR  没有重复的样例输入
 */
View Code

 

posted @ 2015-05-06 20:03  Milkor  阅读(170)  评论(0编辑  收藏  举报