容斥原理 + 大數模板(跳蚤 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<cstdio>
#include<iostream>
#include<bitset>
#include<cstring>
#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<<tot; i++){
            c = 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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章