容斥原理 + 大数模板(跳蚤 POJ - 1091)

欢迎大家来刷我的专题:https://vjudge.net/contest/177165#problem/I
这是一道数范围很大的题,据说数据很水.

首先题目的意识也就是 一个方程有解,系数都是<=m,最后一个系数为m,这个等于1的方程一定有解的话,也就是说这n+1个系数的gcd=1,互质,那么解决问题的思路就有莫比乌斯反演,欧拉函数,容斥原理等等,不过这道题的话,前两个不是很好想.
这里简要说一下容斥原理的思路.
容斥原理: 一共有 mn 种 , 然后只要删掉 gcd>1的情况就行了, 因为已经有了M这个系数,我们就先对他做一个处理,提取他的质因数,如果gcd/2==0,那么也就是 (m/2)n , 考虑容斥,

答案显然就是  

mn(mp1)n(mp2)+...+(mp1p2)+...

#include
#include
#include
#include
#define ll long long
const int maxn = 1e3;
using namespace std;
int tot = 0;
int n,m;

struct BigInt{
    const static int mod = 10;
    int a[maxn], len;
    BigInt(){
        memset(a, 0, sizeof a);
        len = 1;
    }
    BigInt(ll v){
        memset(a, 0, sizeof a);
        len = 0;
        do{
            a[len++] = v%mod;
            v/=mod;
        }while(v);
    }
    BigInt operator +(const BigInt &b)const{
        BigInt res;
        res.len = max(len, b.len);
        for(int i = 0; i <= res.len; i++){
            res.a[i] = 0;
        }
        for(int i = 0; i < res.len; i++){
            res.a[i] += ((i < len)?a[i]:0) + ((i < b.len)?b.a[i]:0);
            res.a[i+1] += res.a[i]/mod;
            res.a[i] %= mod;
        }
        if(res.a[res.len] > 0) res.len++;
        return res;
    }
    //保证a>=b
    BigInt operator -(const BigInt &b)const{
        BigInt res;
        res.len = len;
        for(int i = 0; i <= res.len; i++){
            res.a[i] = 0;
        }
        for(int i = 0; i < res.len; i++){
            res.a[i] += (a[i]-b.a[i]);
            if(res.a[i]<0){
                res.a[i]+=10;
                res.a[i+1]--;
            }
        }
        while(res.a[res.len-1]==0 && res.len > 1)res.len--;
        return res;
    }

    BigInt operator *(const BigInt &b)const{
        BigInt res;
        for(int i = 0; i < len; i++){
            int up = 0;
            for(int j = 0; j < b.len; j++){
                int temp = a[i]*b.a[j] + res.a[i+j] + up;
                res.a[i+j] = temp%mod;
                up = temp/mod;
            }
            if(up != 0)
                res.a[i + b.len] = up;
        }
        res.len = len + b.len;
        while(res.a[res.len - 1] == 0 && res.len > 1)res.len--;
        return res;
    }

    void output(){
        for(int i = len-1; i >= 0; i--)
            printf("%d",a[i]);
    }

    void init(){
        memset(a, 0, sizeof a);
        len = 1;
    }
};

BigInt power(BigInt a, int b){
    BigInt ans = BigInt(1);
    while(b){
        if(b&1) ans = ans*a;
        a = a*a;
        b >>= 1;
    }
    return ans;
}

int p[maxn];

int main(){
    while(~scanf("%d%d",&n,&m)){
        int tot = 0;
        int mm = m;
        for(int i = 2; i <= m/i; i++){
            if(m%i==0){
                p[tot++] = i;
            }
            while(m%i==0){
                m/=i;
            }
        }
        if(m>1){
            p[tot++] = m;
        }
        BigInt ans = power(mm, n);
        ll tmp = 1;
        int c = 0;
        for(int i = 1; i < 1<0; tmp = mm;
            for(int j = 0; j < tot; j++)
            if(i & (1 << j)){
                c++;
                tmp/=p[j];
            }
            BigInt it = BigInt(tmp);
            if(c&1) ans = ans - power(it, n);
            else ans = ans + power(it, n);
            //ans.output();
            //puts("");
        }
        ans.output();
        puts("");
    }
    return 0;
}

你可能感兴趣的:(acm水题,大数,容斥原理,acm)