D. REQ

传送门

题意:
给出一段序列,给出询问,求l, r区间里面的数相乘的数欧拉函数


首先,欧拉函数φ(n)=np|nn(11p), n已经维护好了,到时候求个逆元即可,然后如果能知道l, r区间里面的质数即可,这个可以利用树状数组前缀积的形式,先对所有的区间按r升序,然后离线处理,l = 0开始,然后对于每一个数,如果已经分解的质数已经被处理过了,那就在当前的位置乘以反向的,这样会消除对后面的影响,没有的话就直接,等等,现在只知道一个效果,就是能够维护维护前缀积

点击查看代码
#include <bits/stdc++.h>
#define IOS ios::sync_with_stdio(false);
#define endl '\n'
using namespace std;

typedef long long ll;
const ll MAXN = 1e6 + 10;
const ll MOD = 1e9 + 7;
ll n, q;
ll a[MAXN], fa[MAXN], prime[MAXN], mul[MAXN], ans[MAXN], treea[MAXN];
bool vis[MAXN];
struct Node
{
    ll l, r, id;
} seg[MAXN];

bool comp(Node x, Node y)
{
    if (x.r == y.r)
        return x.l < y.l;
    return x.r < y.r;
}

//线性筛
void get_prime()
{
    int tot = 0;
    for (int i = 2; i < MAXN; ++i)
    {
        if (!vis[i])
            prime[++tot] = i, fa[i] = i;
        for (int j = 1; j <= tot && i * prime[j] < MAXN; ++j)
        {
            vis[i * prime[j]] = true, fa[i * prime[j]] = prime[j];
            if (i % prime[j] == 0)
                break;
        }
    }
}

ll quick_pow(ll base, ll power)
{
    ll ans = 1;
    while (power)
    {
        if (power & 1)
            ans = ans * base % MOD;
        base = base * base % MOD;
        power >>= 1;
    }
    return ans;
}

void add(ll p, ll x)
{
    for (int i = p; i < MAXN; i += i & (-i))
        treea[i] = treea[i] * x % MOD;
}

ll query(ll p)
{
    ll ans = 1;
    for (int i = p; i; i -= i & (-i))
        ans = ans * treea[i] % MOD;
    return ans;
}

int last[MAXN];
void update(ll i)
{
    for (int x = a[i], p = fa[x]; x > 1; p = fa[x])
    {
        add(i, p - 1), add(i, quick_pow(p, MOD - 2));
        if (last[p])
            add(last[p], p), add(last[p], quick_pow(p - 1, MOD - 2));
        last[p] = i;
        while (x % p == 0)
            x /= p;
    }
}

int main()
{
    IOS; cin.tie(0), cout.tie(0);
    cin >> n;
    for (int i = 1; i <= n; ++i)
        cin >> a[i];
    cin >> q;
    for (int i = 1, l, r; i <= q; ++i)
        cin >> seg[i].l >> seg[i].r, seg[i].id = i;
    sort(seg + 1, seg + 1 + q, comp);
    get_prime();
    mul[0] = 1;
    for (int i = 1; i <= n; ++i)
        mul[i] = mul[i - 1] * a[i] % MOD, treea[i] = 1;
    int l = 0;
    for (int i = 1; i <= q; ++i)
    {
        while (l < seg[i].r)
            update(++l);
        ans[seg[i].id] = mul[seg[i].r] % MOD * quick_pow(mul[seg[i].l - 1], MOD - 2) % MOD * query(seg[i].r) % MOD * quick_pow(query(seg[i].l - 1), MOD - 2) % MOD;
    }
    for (int i = 1; i <= q; ++i)
        cout << ans[i] % MOD << endl;
    return 0;
}
/*
1
560149
1
1 1
*/
posted @   YUGUOTIANQING  阅读(23)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 在鹅厂做java开发是什么体验
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性
· 全网最简单!3分钟用满血DeepSeek R1开发一款AI智能客服,零代码轻松接入微信、公众号、小程
点击右上角即可分享
微信分享提示