poj 1091-跳蚤(数论+容斥)

来源:互联网 发布:ps软件什么好 编辑:程序博客网 时间:2024/05/16 03:40

题目链接

题意:


可转化为已知N+1个数,x1, x2, .. xn, m;使得gcd(x1, x2, ..., xn) = 1的解的个数(xi<=m)。

思路:m^n为所有不同序列个数,然后减去公因数>1且为m的素因子的解数,通过容斥原理思想,答案为

ans=m^n-(奇数个m的素因子相乘作为公因子的n元组)+(偶数个m的素因子相乘作为公因子的n元组)。

公因数为d的n元组,每个位置上有 (m/d)个选择(1 ~ m里面有m/d个d的倍数),根据乘法原理,可以得出有公因数d的n元组有 (m/d)^n 个. 

//#pragma comment(linker, "/STACK:1024000000,1024000000")#include<iostream>#include<stdio.h>#include<math.h>#include <string>#include<string.h>#include<map>#include<queue>#include<set>#include<utility>#include<vector>#include<algorithm>#include<stdlib.h>using namespace std;#define eps 1e-8#define pii pair<int,int>#define inf 0x3f3f3f3f#define rd(x) scanf("%d",&x)#define rd2(x,y) scanf("%d%d",&x,&y)#define ll long long int#define mod 1000000007#define maxn 200100#define maxm 10001005int n,m;int pr[maxn],pn;ll pow(ll a,int b){    ll ans=1;    while(b){        if(b&1) ans*=a;        a*=a;        b>>=1;    }    return ans;}int main(){    while(~rd2(n,m)){        ll sum=pow(m,n);        pn=0;        int mm=m;        for(int i=2;i*i<=mm;i++){//m的素因子            if(!(mm%i)) pr[pn++]=i;            while(mm%i==0) mm/=i;        }        if(mm!=1) pr[pn++]=mm;        for(int i=1;i<(1<<pn);i++){//数位枚举所有奇偶素因子情况            int k=1;            ll kk=1;            int nn=0;            for(int j=0;j<pn;j++){                if(k&i) {                    kk*=pr[j];                    nn++;                }                k<<=1;            }            if(nn%2) sum-=pow(m/kk,n);            else sum+=pow(m/kk,n);        }        printf("%I64d\n",sum);    }    return 0;}


0 0
原创粉丝点击