hdu6053_TrickGCD_莫比乌斯反演_快速幂优化_前缀和

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <map>
#define INF 0x3f3f3f3f
#define rep0(i, n) for (int i = 0; i < n; i++)
#define rep1(i, n) for (int i = 1; i <= n; i++)
#define rep_0(i, n) for (int i = n - 1; i >= 0; i--)
#define rep_1(i, n) for (int i = n; i > 0; i--)
#define MAX(x, y) (((x) > (y)) ? (x) : (y))
#define MIN(x, y) (((x) < (y)) ? (x) : (y))
#define mem(x, y) memset(x, y, sizeof(x))

#define MAXN 100010
using namespace std;

typedef long long ll;
const ll mod = 1e9 + 7;
bool vis[MAXN];
int primes[MAXN];
int miu[MAXN], a[MAXN], n;
int calc(int limit)
{
    memset(vis, false, sizeof(vis));
    memset(miu, 0, sizeof(miu));

    int tot = 0;
    miu[1] = 1;
    pre[1] = 1;

    for(int i = 2; i <= limit; i++)
    {
        if(!vis[i])
        {
            primes[tot++] = i;
            miu[i] = -1;

        }
        for(int j = 0; j < tot; j++)
        {
            int k = i * primes[j];

            if(k > limit)
                break;
            vis[k] = true;
            if(i % primes[j])
            {
                miu[k] = -miu[i];

            }
            else
                break;
        }

    }
}
int mn, mx;
ll tot;
int sum[MAXN];

ll multi(ll a, int t)
{
    ll ans = 1;
    while (t)
    {
        if (t & 1)
        {
            ans = (ans * a) % mod;

        }
        a = (a * a) % mod;
        t >>= 1;
    }
    return ans;
}
ll solve()
{
    int last;
    ll ans = tot;
    for (int d = 2; d <= mn; d++)
    {
        if (!miu[d])
            continue;
        ll tmp = 1;
        for (int i = 1; i <= mx / d; i++)
        {
            tmp = tmp * multi(i, sum[MIN(d * (i + 1), mx + 1) - 1] - sum[d * i - 1]) % mod;  /**runtime error */
        }

        ans = (ans + (tmp * miu[d] + mod) % mod) % mod;

    }
    return ans;
}
int main()
{
    #ifndef ONLINE_JUDGE
        freopen("in.txt", "r", stdin);
    #endif // ONLINE_JUDGE
    //calc(500);
    int t, kase = 0;
    calc(MAXN - 2);
    scanf("%d", &t);

    while (t--)
    {
        mem(sum, 0);
        scanf("%d", &n);
        mn = INF;
        mx = 0;
        tot = 1;
        for (int i = 0; i < n; i++)
        {
            scanf("%d", a + i);
            mn = MIN(mn, a[i]);
            mx = MAX(mx, a[i]);
            tot = (tot * a[i]) % mod;
            sum[a[i]]++;

        }
        for (int i = mn; i < MAXN; i++)
            sum[i] += sum[i - 1];             /**前缀维护*/

        ll ans = (tot - solve() + mod) % mod;
        printf("Case #%d: %lld\n", ++kase, ans);


    }




    return 0;
}

猜你喜欢

转载自blog.csdn.net/Anna__1997/article/details/79807310