您的位置:首页 > 其它

HDU 6053 TrickGCD(莫比乌斯反演)

2017-07-30 14:10 351 查看
Description

一个长度为n的序列b[1]~b
序满足gcd(b[l],…,b[r])>=2,1<=l<=r<=n,1<=b[i]<=a[i],给出a[1]~a
,问满足条件的b序列个数

Input

第一行一整数T表示用例组数,每组用例首先输入一整数n表示序列长度,之后输入n个整数a[i] (1<=T<=10,1<=n,a[i]<=1e5)

Output

对于每组用例,输出满足条件的b序列个数,结果模1e9+7

Sample Input

1

4

4 4 4 4

Sample Output

Case #1: 17

Solution



Code

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<set>
#include<ctime>
using namespace std;
typedef long long ll;
#define INF 0x3f3f3f3f
#define maxn 111111
#define mod 1000000007
typedef long long ll;
bool check[maxn];
int prime[maxn],mu[maxn];
void Moblus(int n=100000)
{
memset(check,0,sizeof(check));
mu[1]=1;
int tot=0;
for(int i=2;i<=n;i++)
{
if(!check[i])
{
prime[tot++]=i;
mu[i]=-1;
}
for(int j=0;j<tot;j++)
{
if(i*prime[j]>n)break;
check[i*prime[j]]=1;
if(i%prime[j]==0)
{
mu[i*prime[j]]=0;
break;
}
mu[i*prime[j]]=-mu[i];
}
}
}
int a[maxn],num[maxn],cnt[maxn];
ll ans[maxn];
ll mod_pow(ll a,ll b)
{
ll ans=1;
while(b)
{
if(b&1)ans=ans*a%mod;
a=a*a%mod;
b>>=1;
}
return ans;
}
int main()
{
Moblus();
int T,Case=1,n;
scanf("%d",&T);
while(T--)
{
memset(a,0,sizeof(a));
memset(ans,0,sizeof(ans));
scanf("%d",&n);
int Min=1e5;
for(int i=1;i<=n;i++)
{
int temp;
scanf("%d",&temp);
Min=min(Min,temp);
a[temp]++;
}
for(int i=1;i<=1e5;i++)a[i]+=a[i-1];
for(int i=2;i<=Min;i++)ans[i]=1;
for(int i=2;i<=Min;i++)
{
for(int j=1;j*i<=1e5;j++)
ans[i]=ans[i]*mod_pow(j,a[min((j+1)*i-1,100000)]-a[j*i-1])%mod;
}
ll sum=0;
for(int i=2;i<=Min;i++)
{
sum=(sum-mu[i]*ans[i])%mod;
if(sum<0)sum+=mod;
}
printf("Case #%d: %I64d\n",Case++,sum);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: