样例输入1:
2 3
样例输出1:
8
样例输入2:
8 8
样例输出2:
16711680
题目分析:
考场总结:对于这道题无话可说,有一种难度叫读不懂题。考试时前面题花的时间比较多,然后面对这道长达2页的题(以某种鬼畜的言情风格写了一大堆废话包裹题面),我愣是没有读懂,实际上这道题的题目要求转化一下,就比较简单(以前还做过一道这样的题,那道题的题面没有这么复杂),比前面的两道都还简单·····所以啊,一道题不够难,可以通过题面来增加其难度。
分析:所以这道题最后的意思就是求给定m,选取n个小于等于m的数(可以相同),使得这个n+1数整体互质及gcd为1,有多少种组合。那么我们可以用整体减不互质的组合。整体是
附代码:
#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;
}