題意
給定一個長爲n的數組A,求解一定條件下能構造多少個不同數組B。條件爲
分析
顯然gcd最小的情況必然是在
代碼
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<map>
#include<cmath>
#include<queue>
using namespace std;
const int N = 100000 + 10;
const int mod = 1e9 + 7;
int T, n, a[N], ca[N*2], inv[N] = {0, 1}, cnt[N], vis[N];
int mn, mx;
long long quick_pow(long long a,long long b){
long long ret=1;
while(b){
if(b&1)
ret=(ret*a)%mod;
b>>=1;
a=(a*a)%mod;
}
return ret;
}
bool isSqr[N];
int lowbit(int x){
return x&-x;
}
void prime() {
memset(isSqr, 0, sizeof(isSqr));
for(int i=2;i<=100000;i++)
{
if(cnt[i]) continue;
for(int j=i;j<=100000;j+=i) {
cnt[j]++;
if(j % (i*i) == 0) isSqr[j] = 1;
}
}
}
int getnum(int k){
long long ret=1;
for(int i=1;i<=100000;++i){
if(k*i>mx)
break;
int num=ca[k*(i+1)-1]-ca[k*i-1];
if(num==0)
continue;
ret*=quick_pow(i,num);
if(ret>mod)
ret%=mod;
}
return ret;
}
int main()
{
for(int i=2;i<N;i++)
inv[i] = (mod - mod/i) *1ll* inv[mod%i] % mod;
prime();
scanf("%d", &T);
for(int ica=1;ica<=T;ica++)
{
scanf("%d", &n);
memset(ca,0,sizeof(ca));
mn=100000,mx=0;
for(int i=1;i<=n;i++)
{
scanf("%d", &a[i]);
mn = min(mn, a[i]);
mx = max(mx,a[i]);
ca[a[i]]++;
}
if(mn == 1) {
printf("Case #%d: 0\n", ica);
continue;
}
for(int i=2;i<N*2;++i)
ca[i]+=ca[i-1];
int ans = 0;
int func = 1;
for(int i=2;i<=mn;i++)
{
func=getnum(i);
if(isSqr[i]) continue;
if(cnt[i] % 2) ans += func;
else ans -= func;
ans%=mod;
}
ans=(ans+mod)%mod;
printf("Case #%d: %d\n", ica, ans);
}
}