【NOIP2017提高A组模拟9.5】心灵治愈

来源:互联网 发布:安卓手游刷元宝软件 编辑:程序博客网 时间:2024/06/07 03:37

题目

这里写图片描述
好吧,我表示比赛时完全看不懂题目

题目解释

这里写图片描述
良心的出题人为一道两三句可以讲清楚的题目,又写了一大坨恶心的解释。

容斥

其实题目就是有个数组a[1~n+1],已知a[n+1]=m,1<=a[1~n]<=m,求a数组的每个数的最大公因数为1的方案数。
正难则反,
用a树数组的可能总数为m^n,减去最大公因数不为1的总数。
直接求出m的质数,容斥一下就可以了。

#include <cmath>#include <iostream>#include <cstdio>#include <cstdlib>#include <cstring>#include <algorithm>#include <queue>#include <map>const int maxlongint=2147483647;const int mo=1e9+7;const int N=100005;using namespace std;long long p[N],n,m,ans;long long mi(long long x,long long y){    long long sum=1;    x%=mo;    while(y)    {        if(y&1) sum=sum*x%mo;        x=x*x%mo;        y>>=1;    }    return sum;}void dg(int x,long long val,long long t){    if(x>p[0])    {        ans=(ans+mi(m/val,n)*t+mo)%mo;        return;    }    dg(x+1,val,t);    dg(x+1,val*p[x],-t);}int main(){    scanf("%lld%lld",&n,&m);    long long qm=sqrt(m),m1=m;    for(long long i=2;i<=qm;i++)        if(m1%i==0)        {            p[++p[0]]=i;            while(m1%i==0) m1/=i;        }    if(m1>1) p[++p[0]]=m1;    dg(1,1ll,1);    printf("%lld",ans);}