[NOIP模拟][容斥原理][快速幂]Heal

来源:互联网 发布:maven java项目打包 编辑:程序博客网 时间:2024/05/09 06:14

样例输入1:

2 3

样例输出1:

8

样例输入2:

8 8

样例输出2:

16711680

题目分析:
考场总结:对于这道题无话可说,有一种难度叫读不懂题。考试时前面题花的时间比较多,然后面对这道长达2页的题(以某种鬼畜的言情风格写了一大堆废话包裹题面),我愣是没有读懂,实际上这道题的题目要求转化一下,就比较简单(以前还做过一道这样的题,那道题的题面没有这么复杂),比前面的两道都还简单·····所以啊,一道题不够难,可以通过题面来增加其难度。
分析:所以这道题最后的意思就是求给定m,选取n个小于等于m的数(可以相同),使得这个n+1数整体互质及gcd为1,有多少种组合。那么我们可以用整体减不互质的组合。整体是mn(因为可以取相同的数)。而m是已知的,所以求出m的质因子,如果整体不互质,那么gcd只能是m的约数,所以容斥:减去gcd为一个质因子的个数的n次方,加上gcd为两个质因子的乘积的个数的n次方,减去3个·········
附代码:

#include<iostream>#include<cstring>#include<string>#include<cstdlib>#include<cstdio>#include<ctime>#include<cmath>#include<iomanip>#include<cctype>#include<algorithm>using namespace std;const int mod=1e9+7;const int N=1e6;int tot,num;long long n,m,q[N],zhi[N],ans,p;long long ksm(long long x,long long y){    long long ret=1;    x%=mod;    for(;y;y/=2,x=(x*x)%mod)        if(y&1) ret=(ret*x)%mod;    return ret;}void dfs(int cnt,int po,long long sum)//求一定个数质因子的乘积{    if(cnt==0)    {        q[++tot]=sum;        return;    }    for(int i=po;i<=num;i++)        dfs(cnt-1,i+1,sum*zhi[i]);}void find(int x,int ci)//容斥{    if(x==0) return;    tot=0;    dfs(num-x+1,1,1);    for(int i=1;i<=tot-cnt+1;i++)        ans=(ans+mod+ksm(m/q[i],n)*ci)%mod;    find(x-1,ci*(-1));}int main(){    //freopen("heal.in","r",stdin);    //freopen("heal.out","w",stdout);    scanf("%I64d%I64d",&n,&m);    p=m;    for(long long i=2;i*i<=p;i++)//求m的质因子    {        if(p%i==0)        {            zhi[++num]=i;            while(p%i==0)            {                p/=i;            }        }    }       if(p>1) zhi[++num]=p;    ans=ksm(m,n);    find(num,-1);    printf("%I64d",ans);    return 0;}
阅读全文
0 0
原创粉丝点击