Problem Description
You are given an array A , and Zhu wants to know there are how many different array B satisfy the following conditions?

  • 1≤Bi≤Ai
  • For each pair( l , r ) (1≤l≤r≤n) , gcd(bl,bl+1…br)≥2

Input
The first line is an integer T(1≤T≤10) describe the number of test cases.

Each test case begins with an integer number n describe the size of array A.

Then a line contains n numbers describe each element of A

You can assume that 1≤n,Ai≤105

Output
For the kth test case , first output “Case #k: ” , then output an integer as answer in a single line . because the answer may be large , so you are only need to output answer mod 109+7

Sample Input

1
4
4 4 4 4

Sample Output

Case #1: 17

题意:给出长度为n的A数列,求满足条件的B数组的个数,条件:①1<=b[i]<=a[i] ②对于任意区间【L,R】,区间gcd>=2
解法:除了上一篇文章的容斥求法,还有可以直接利用Mobius来求。对于某个数及其倍数能产生的B数组方案个数为:

但其中会产生重复的数列,这时候我们需要判断x的质因子数的奇偶性,若为奇数则加上该方案数,否则减去该方案数(容斥原理)可以用莫比乌斯函数判断当前枚举的GCD对答案的贡献。

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn = 1e5+7;
const int huyu = 1e9+7;
LL mu[maxn], num[2*maxn], ks = 0;
void Mobius(LL n){
    mu[1] = 1;
    for(LL i=1; i<=n; i++){
        for(LL j=i+i; j<=n; j+=i){
            mu[j]-=mu[i];
        }
    }
}
LL qsm(LL b, LL n){
    LL ret = 1;
    while(n){
        if(n&1) ret = ret*b%huyu;
        b=b*b%huyu;
        n>>=1;
    }
    return ret;
}

int main()
{
    Mobius(100000);
    int T,n;
    scanf("%d", &T);
    while(T--)
    {
        memset(num, 0, sizeof(num));
        scanf("%d", &n);
        int mi = 1e9;
        for(int i=1; i<=n; i++){
            int x;
            scanf("%d", &x);
            mi = min(mi, x);
            num[x]++;
        }
        for(int i=1; i<=200000; i++){
            num[i]+=num[i-1];
        }
        LL sum = 0;
        for(LL i=2; i<=mi; i++){
            LL f = 1;
            for(LL j=1; j*i<=100000; j++){
                f = (f*qsm(1LL*j, num[(j+1)*i-1]-num[j*i-1]))%huyu;
            }
            sum = ((sum - f * mu[i]% huyu) + huyu) %huyu;
        }
        printf("Case #%d: ", ++ks);
        printf("%lld\n",sum);
    }
    return 0;
}