歌名 - 歌手
0:00

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

    题目

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

    题目解释

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

    容斥

    其实题目就是有个数组a[1n+1],已知a[n+1]=m,1<=a[1n]<=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);
    }
    
    posted @ 2018-05-23 21:41  无尽的蓝黄  阅读(188)  评论(0编辑  收藏  举报