题目链接<http://acm.hdu.edu.cn/showproblem.php?pid=6053>
题意:
有一个长度为N的数组a,问数组b有多少种情况,满足
1<=N,a[i]<=1e5
题解:
第二个条件其实就是,如果所有数字的gcd都大于等于2,那部分的也肯定大于等于2。
假设,则。设为的方案数,则。这样我们就可以枚举来进行容斥的运算,而且我们也可以发现,容斥的系数就是负的莫比乌斯函数。所以最后的答案就是
因为的数据范围在1e5内,所以对于,我们可以通过筛法来求。预处理的前缀和,筛法求的值的个数,然后通过快速幂求出值。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef double db;
const ll N=1e5+7;
const ll mod=1e9+7;
ll a[N],t,cs,n,s[N],cnt;
bool vis[N];
ll pri[N],pt,mu[N],sum[N];
void getmu(){
mu[1]=1;
memset(vis,false,sizeof(vis));
for(ll i=2;i<N;i++){
if(!vis[i]){
pri[++pt]=i;
mu[i]=-1;
}
for(ll j=1;j<=pt&&i*pri[j]<N;j++){
vis[i*pri[j]]=true;
if(i%pri[j]) mu[i*pri[j]]=-mu[i];
else{
mu[i*pri[j]]=0;
break;
}
}
}
}
ll qpow(ll x,ll y){
ll res=1;
while(y){
if(y&1) res=res*x%mod;
y>>=1;x=x*x%mod;
}
return res;
}
int main(){
scanf("%lld",&t);
getmu();
while(t--){
scanf("%lld",&n);
ll mi=N,ma=0;
memset(sum,0,sizeof(sum));
for(ll i=1;i<=n;i++){
scanf("%lld",&a[i]);
sum[a[i]]++;
mi=min(mi,a[i]);
ma=max(ma,a[i]);
}
for(ll i=1;i<=ma;i++) sum[i]+=sum[i-1];
ll ans=0;
for(ll d=2;d<=mi;d++){
ll tmp=1;
for(ll j=1;d*j<=ma;j++){
tmp=tmp*qpow(j,sum[min(ma,d*(j+1)-1)]-sum[d*j-1])%mod;
}
ans=(ans+(-mu[d]*tmp+mod)%mod)%mod;
}
printf("Case #%lld: %lld\n",++cs,ans);
}
}