[HDU]6053 TrickGCD

来源:互联网 发布:淘宝体检中心进不去 编辑:程序博客网 时间:2024/05/20 02:53

TrickGCD

URL: http://acm.hdu.edu.cn/showproblem.php?pid=6053

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

题解

莫比乌斯&容斥

ans=d=2nμ(d)i=1nain

转化一下
ans=d=2nμ(d)i=1max(ai)nitimes(i,d)

其中
times(i,d)=akd=i1

#include<stdio.h>#include<string.h>#include<algorithm>using namespace std;typedef long long LL;const int MAXN = 1e5 + 5;const int MOD = 1e9 + 7;bool notp[MAXN];int prime[MAXN], mu[MAXN], sz;void init() {    for(int i = 2; i < MAXN ; ++i) {        if(!notp[i]) {            mu[i] = -1;            prime[sz++] = i;        }        for(int j = 0; j < sz; ++j) {            int t = i * prime[j];            if(t >= MAXN) break;            notp[t] = true;            if(i % prime[j]) {                mu[t] = -mu[i];            } else {                mu[t] = 0;                break;            }        }    }}int pow(int a, int n) {    int res = 1;    while(n) {        if(n&1) res = 1LL * res * a % MOD;        a = 1LL * a * a % MOD;        n >>= 1;    }    return res;}int dp[MAXN], num[MAXN], T, n, low, top;void slove(int Case) {    int pos = 0, mul = 1, ans = 0;    for(int i = 2; i <= top; ++i) {        num[i] += num[i - 1];    }    for(int d = 2; d <= low; ++d) {        int res = -mu[d];        for(int i = 1; i <= top/d; ++i) {            res = 1LL * res * pow(i, num[min(i * d + d - 1, top)] - num[i * d - 1]) % MOD;        }        ans = (ans + res) % MOD;    }    printf("Case #%d: %d\n", Case, (ans + MOD) % MOD);}int main(){    init();    /*    for(int i = 2; i < 20; ++i) {        printf("%-2d %d\n", i, mu[i]);    }    */    scanf("%d", &T);    for(int Case = 1; Case <= T; ++Case) {        memset(num, 0, sizeof(num));        low = 1 << 30, top = 0;        scanf("%d", &n);        for(int i = 0; i < n; ++i) {            int x;            scanf("%d", &x);            ++num[x];            low = min(low, x);            top = max(top, x);        }        slove(Case);    }    return 0;}