题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6053
题目大意:给一个长度为n的数组,构造出一个长度为n的数组满足1≤Bi≤Ai,且任意区间gcd>=2;
思路:对于每一个gcd都有a[i]/gcd个然后把每个值乘起来,对于所有序列的重复性恰好为莫比乌斯函数的规律。(莫比乌斯函数+容斥+筛法)
#include <bits/stdc++.h>
#define FAST ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
using namespace std;
typedef long long ll;
const ll maxn=3e5+100;
const ll MAXN=2e5 + 5;
const ll mod=1e9+7;
bool isprime[maxn];
ll prime[maxn];
ll mu[maxn];
void getprime()
{
ll cnt=0;
mu[1]=1;
isprime[0]=isprime[1]=1;
for(ll i=2;i<maxn;i++)
{
if(!isprime[i])
{
prime[cnt++]=i;
mu[i]=-1;
}
for(ll j=0;j<cnt&&prime[j]*i<maxn;j++)
{
ll x=prime[j]*i;
isprime[x]=1;
if(i%prime[j]==0)
{
break;
}
mu[x]=-mu[i];
}
}
for(ll i=2;i<maxn;i++)
{
mu[i]=-mu[i];
}
}
ll poww(ll a,ll b)
{
ll res=1;
while(b)
{
if(b&1) res=res*a%mod;
b/=2;
a=a*a%mod;
}
return res;
}
ll a[maxn];
ll sum[maxn];
int main()
{
getprime();
FAST;
ll t;
cin>>t;
for(ll kcase=1;kcase<=t;kcase++)
{
ll n;
cin>>n;
memset(sum,0,sizeof(sum));
for(ll i=1;i<=n;i++)
{
cin>>a[i];
sum[a[i]]++;
}
sort(a+1,a+1+n);
for(ll i=1;i<=2e5;i++)
{
sum[i]=sum[i-1]+sum[i];
}
ll ans=0;
for(ll i=2;i<=a[1];i++)
{
ll num=1;
for(ll j=i;j<=1e5;j=j+i)
{
num=(num*poww(j/i,(sum[j+i-1]-sum[j-1])))%mod;
}
ans=(ans+mu[i]*num+mod)%mod;
}
cout<<"Case #"<<kcase<<": "<<ans<<endl;
}
}
/*
1
4
4 4 4 4
*/