莫比乌斯的函数的一个应用,补题的时候怒补了一波莫比乌斯。但是到现在还是一知半解的,这题大致就是要算每一个数的倍数的个数,但是如果枚举每一个Ai的话铁定还会超时,那么就要想到优化,cnt数组就是这样的一个优化,cnt[i]就是小于等于i数的个数,相当于前缀和,然后再用莫比乌斯的u函数容斥,这里保存一下在别人博客看到的莫比乌斯函数的几个形式。。方便以后查看。
详情点击:点击打开链接
定理:和
是定义在非负整数集合上的两个函数,并且满足条件
,那么我们得到结论
在上面的公式中有一个函数,它的定义如下:
(1)若,那么
(2)若,
均为互异素数,那么
(3)其它情况下
对于函数,它有如下的常见性质:
(1)对任意正整数有
(2)对任意正整数有
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <algorithm>
#define siz 100005
#define LL long long
using namespace std;
int gp[siz];
int n;
int mu[siz];
const LL mod=1e9+7;
int maxx,cnt[siz*2];
LL quck_mod(LL x,LL y){
LL ret=1;
while(y>0){
if(y&1) ret=ret*x%mod;
x=x*x%mod;
y>>=1;
}
return ret;
}
void _u(){
mu[1]=1;
for(int i=1;i<siz;i++){
for(int j=i+i;j<siz;j+=i){
mu[j]-=mu[i];;
}
}
}
void solve(){
LL ans=0;
for(int i=2;i<=maxx;i++){
LL temp=1;
for(int j=1;i*j<=100000;j++){
temp=(temp*quck_mod((LL)j,cnt[i*j+i-1]-cnt[i*j-1]))%mod;
// cout<<temp<<endl;
}
ans=(ans-temp*mu[i]+mod)%mod;
}
printf("%I64d\n",ans);
}
int main()
{
_u();
int t;
scanf("%d",&t);
for(int i=1;i<=t;i++){
scanf("%d",&n);
maxx=100000;
for(int j=1;j<2*siz;j++){
cnt[j]=0;
}
for(int j=1;j<=n;j++){
scanf("%d",&gp[j]);
cnt[gp[j]]++;
maxx=min(maxx,gp[j]);
}
for(int j=1;j<2*siz;j++) cnt[j]+=cnt[j-1];
printf("Case #%d: ",i);
solve();
}
return 0;
}