您的位置:首页 > 其它

容斥原理+欧拉函数

2018-01-24 13:02 211 查看
HDU :

2588:欧拉函数于gcd

1286:

4135:

2841:

2824:

1796:

1695:

3501:欧拉函数扩展

POJ :

1142:

2407:

3090:

总结:

容斥原理:求n在(1,m)中有几个互质的数。

[b]基本步骤:[/b]

[b]1.求n的质因子[/b]

[b]2.求质因子的组合(奇正,偶负)//队列法,位运算法[/b]

[b]3.求和得(1,m)中于质因子有关的数的数量[/b]

[b]4.m - f(m);[/b]

队列法:

int k;//质因子数量

int e[1000];//存放质因子

int p[10000];//存放欧拉函数

void ff(int n)//求质因子

{

    k = 0;

    for(int i = 2;i * i <= n;i++)

    {

        if(n % i == 0)

        {

            e[k++] = i;

            while(n % i == 0){n /= i;}

        }

    }

    if(n > 1) e[k++] = n;

}

int f(int m)

{

    int top = 1;

    p[0] = -1;

    for(int i = 0;i < k;i++)//求组合

    {

        int t = top;

        for(int j = 0;j < top;j++)

        {

            p[top++] = p[j] * (-1) * e[i];

        }

    }

    int sum = 0;

    for(int i = 1;i < top;i++)//求和

    {

        sum += m / p[i];

    }

    return sum;

}


位运算法:复杂度=1<<k (k=n的质因子数)

int k;//质因子数量

int e[1000];//存放质因子

void ff(int n)//求质因子

{

    k = 0;

    for(int i = 2;i * i <= n;i++)

    {

        if(n % i == 0)

        {

            e[k++] = i;

            while(n % i == 0){n /= i;}

        }

    }

    if(n > 1) e[k++] = n;

}

int f(int m)  

{

    int res;  

    int sum = 0;  

    int use;//记录使用因子的个数 

    for(int i = 1; i < 1<<k; i++)

    {  

        res = 1; use = 0;  

        for(j = 0; j < k; j++)  

        {  

            if(i & (1<<j))  

            {  

                use++;  

                res *= e[j];

            }  

        }  

        if(use & 1) sum += m / res;//奇加偶减 

        else sum -= m / res;  

    }  

    return sum;  

}


欧拉函数:求n在(1,n)中有几个互质的数。

欧拉函数扩展:小于或者等于n的数中(n > 1),与n互

质的数总和
= euler
* n / 2。


重要应用于gcd结合!!

基本公式:a
=n * (1 - 1 / pi) * (1 - 1 / pj)...(pi,j为n的质因子)。


代码1:求单个n的欧拉值。//适用于n大,n少。

int f(int n)

{

    int sum = n;

    for(int i = 2;i * i <= n;i++)

    {

        if(n % i == 0)

        {

            sum = sum * (i - 1) / i;

            n /= i;

            while(n % i == 0){n /= i;}

        }

    }

    if(n > 1) sum = sum * (n - 1) / n;

    return sum;

}


代码2:求(1,n)中所有的欧拉值a[i]。//[b]适用于n小,n多。[/b]

[b]void f(int n)

{

    memset(p,0,sizeof(p));

    p[1] = 1;

    for(int i = 2;i <= n;i++)

    {

        if(!p[i])

        {

            for(int j = i;j <= n;j += i)

            {

                if(!p[j]) p[j] = j;

                p[j] = p[j] * (i - 1) / i;

            }

        }

    }

}
[/b]









内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: