poj 1091 跳蚤 (数论,容斥原理)

来源:互联网 发布:网络摄像头 监控软件 编辑:程序博客网 时间:2024/05/02 01:08

题意:

一只小跳蚤想要迟到它左边的食物,但是跳蚤只能按照某张牌上的数字进行往左或者往右的跳跃。牌中数字有N+1个,并且最后一个一定是M,其他的不比M大。问在所有的组合M^N中有多少张牌是可以让跳蚤迟到食物的。注意,牌上的数字可以重复使用。

题解:

这种题目下手要寻找一个规律,规律就是突破口,我们要得到那些性质的数组成的牌能让跳蚤迟到食物。发现这些数如果公约数为1那么跳蚤就可以吃到食物,那么我们求逆问题,哪些数公约数大于1,既然M是固定的,那么要满足公约是大于1,其他的数必定要与M不互质!那么与M不互质的数可定是M质因子的倍数,那么对于某个质因数它能得到的方案树:(M/x)^N。但是会发现某写x^2等于某些y^3这里含着重复,于是根据容斥原理,dfs求解。

#include<iostream>#include<math.h>#include<stdio.h>#include<algorithm>#include<string.h>#include<string>#include<vector>#include<queue>#include<map>#include<set>using namespace std;#define B(x) (1<<(x))void cmax(int& a,int b){ if(b>a)a=b; }void cmin(int& a,int b){ if(b<a)a=b; }typedef long long ll;const int oo=0x3f3f3f3f;const ll OO=1LL<<61;const int MOD=1000007;const int maxn=100005;set<ll>g;ll N,M;ll quick_pow(ll a,ll k){    ll ans=1;    while(k){        if(k&1) ans*=a;        a*=a;        k>>=1;    }    return ans;}ll dfs(set<ll>::iterator s,ll x){    ll res=0,cnt,t;    for(set<ll>::iterator it=s;it!=g.end();++it){        t=x/(*it);        cnt=quick_pow(t,N);        it++;        res+=cnt-dfs(it,t);        it--;    }    return res;}void fac(ll n){    g.clear();    for(int i=2;i*i<=n;i++){        while(n%i==0){            g.insert(i);            n/=i;        }    }    if(n>1)        g.insert(n);}int main(){    //freopen("E:\\read.txt","r",stdin);    int T;    while(scanf("%I64d %I64d",&N,&M)!=EOF){        fac(M);        ll ans=quick_pow(M,N)-dfs(g.begin(),M);        printf("%I64d\n",ans);    }    return 0;}




0 0
原创粉丝点击