zoukankan      html  css  js  c++  java
  • poj1091 容斥原理的应用

      这个题的意思是给你n+1个数, a1 a2 ... an an+1 其中 1<=ai<=M  i!=n+1  an+1 = M, 求解存在x1..xn+1使x1*a1+x2*a2+x3*a3+..+xn+1*an+1 = 1的a序列的个数, 由数论部分知识我们可以知道上式要满足就得使(a1, a2, a3, .. an, an+1) = 1,   我们还能知道存在一些a序列他们的最大公约数不等于1, 然而我们要统计其中最大公约数为1的个数, 就可以使用容斥原理, 稍加思考我们可以发现(a1, a2 .. an+1) = 1的反面是(a1, a2, ... an+1)= pi的倍数, pi是M = pi^ai次方中的pi, 因此我们定义Ai为a序列最大公约数为pi的倍数的方案数根据容斥原理有 res = s - (A1+A2+...Ak) + (Ai并Aj i!=j) - ...... 代码如下:

    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    #include <iostream>
    #include <cmath>
    
    using namespace std;
    typedef long long LL;
    const int maxn = 100000 + 10;
    LL N, M;
    LL pi[maxn], npi;
    
    bool vis[maxn];
    int prime[maxn], num;
    void shai(int n)
    {
        memset(vis, 0, sizeof(vis));
        int m = sqrt(n+0.5);
        for(int i=2; i<=m; i++) if(!vis[i])
            for(int j=i*i; j<=n; j+=i) vis[j] = 1;
        num = 0;
        for(int i=2; i<=n; i++) if(vis[i] == 0)
            prime[num++] = i;
    }
    
    LL pow(LL A, LL B)  // A^B
    {
        LL res = 1;
        while(B > 0)
        {
            if(B%2 == 1)
                res = res * A;
            A = A*A;
            B /= 2;
        }
        return res;
    }
    
    
    int main()
    {
        shai(20010);
        while( cin>>N>>M )
        {
            LL tp = M;
            npi = 0;
            for(int i=0; i<num; i++)
            {
                bool flog = false;
                while(tp%prime[i] == 0)
                {
                    tp /= prime[i];
                    pi[npi] = prime[i];
                    flog = true;
                }
                if(flog) npi++;
                if(tp == 1) break;
            }
            if(tp!=1) pi[npi++] = tp;              //这里出完所有素数后有可能不为1
            LL res = 0;
            for(int i=1; i<(1<<npi); i++)
            {
                LL ge=0, d=1;
                for(int j=0; j<npi; j++)
                    if(((i>>j)&1) == 1) ge++, d*=pi[j];
                if(ge%2==1) res -= pow(M/d, N);
                else res += pow(M/d, N);
            }
            cout<<res+pow(M, N)<<endl;
        }
        return 0;
    }
  • 相关阅读:
    Linux
    python中元类
    POJ 1182 食物链
    POJ 1733 Parity game
    top 介绍
    周记 2014.8.31
    windows10配置python
    oracle执行update时卡死问题的解决办法
    An Easy Introduction to CUDA C and C++
    super()
  • 原文地址:https://www.cnblogs.com/xingxing1024/p/5213536.html
Copyright © 2011-2022 走看看