• CF1114F Please, another Queries on Array?【线段树+欧拉函数】


    题意

    你有一个数组 a 1 , a 2 , … , a n a_1,a_2,\dots,a_n a1,a2,,an

    现在你需要完成 q q q次操作,有以下两种操作形式:

    1. MULTIPLY l r x,对于所有 i ( l ≤ i ≤ r ) i(l\le i\le r) i(lir),将 a i a_i ai乘上 x x x

    2. TOTIENT l r,求出 φ ( ∏ i = l r a i ) \varphi(\prod_{i=l}^ra_i) φ(i=lrai),对 1 0 9 + 7 10^9+7 109+7取模后的结果。其中 φ \varphi φ表示欧拉函数, φ ( n ) \varphi(n) φ(n)的定义为 1 … n 1\dots n 1n中与 n n n互质的数的个数。

    时间限制

    5.50s

    内存限制

    250.00MB

    思路

    对于某个数的欧拉函数,可以通过质因数分解求解,若 a = ∑ i p i α i a = \sum_ip_i^{\alpha_i} a=ipiαi,那么 φ ( a ) = a ∏ i p i − 1 p i \varphi(a) = a\prod_i\frac{p_i - 1}{p_i} φ(a)=aipipi1
    同时,观察到每个数的大小只有300,通过猜想与打表验证之后发现300以内的质数只有62个,那么可以把是否包含这些素数用 l o n g   l o n g long\ long long long状压起来。用线段树维护每一个区间所有数的乘积极其包含的质因数即可。
    维护每个区间数的乘积就是维护乘法而已,非常简单。
    维护每个区间数的乘积包含的质因数,由于状压起来了,那么两个子区间的状态进行或运算就可以。

    代码

    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    
    using namespace std;
    
    typedef long long LL;
    typedef pair<int, int> PII;
    
    const int N = 400005, mod = 1000000007;
    
    int n, m;
    int a[N];
    int p[305];
    bool vis[305];
    
    struct Tree
    {
        int l, r;
        LL pstate; int mul;
        LL plz; int mullz;
    }t[N << 2];
    
    void get_prime(int n)
    {
        for (int i = 2; i <= n; i ++ )
        {
            if (!vis[i]) p[++ p[0]] = i;
            for (int j = 1; j <= p[0] && i * p[j] <= n; j ++ )
            {
                vis[i * p[j]] = true;
                if (i % p[j] == 0) break;
            }
        }
    }
    
    int qpow(int a, int b)
    {
        int res = 1;
        while (b)
        {
            if (b & 1) res = 1LL * res * a % mod;
            b >>= 1;
            a = 1LL * a * a % mod;
        }
        return res;
    }
    
    void push_up(int i)
    {
        t[i].mul = 1LL * t[i << 1].mul * t[i << 1 | 1].mul % mod;
        t[i].pstate = t[i << 1].pstate | t[i << 1 | 1].pstate;
    }
    
    void calc(int i, int mul, LL state)
    {
        t[i].mul = 1LL * t[i].mul * qpow(mul, t[i].r - t[i].l + 1) % mod;
        t[i].pstate |= state;
        t[i].mullz = 1LL * t[i].mullz * mul % mod;
        t[i].plz |= state;
    }
    
    void push_down(int i)
    {
        if (!t[i].plz) return;
        int mul = t[i].mullz;
        LL state = t[i].plz;
        calc(i << 1, mul, state);
        calc(i << 1 | 1, mul, state);
        t[i].plz = 0, t[i].mullz = 1;    
    }
    
    void build(int i, int l, int r)
    {
        t[i].l = l, t[i].r = r;
        t[i].mul = 1, t[i].mullz = 1;
        if (l == r)
        {
            int x = a[l];
            t[i].mul = x;
            for (int j = 1; j <= p[0]; j ++ )
                if (x % p[j] == 0)
                    t[i].pstate |= 1LL << (j - 1);
            return;
        }
        int mid = (l + r) >> 1;
        build(i << 1, l, mid);
        build(i << 1 | 1, mid + 1, r);
        push_up(i);
    }
    
    void update(int i, int l, int r, int x, LL xp)
    {
        if (l <= t[i].l && t[i].r <= r)
        {
            calc(i, x, xp);
            return;
        }
        push_down(i);
        int mid = (t[i].l + t[i].r) >> 1;
        if (l <= mid) update(i << 1, l, r, x, xp);
        if (r > mid) update(i << 1 | 1, l, r, x, xp);
        push_up(i);
    }
    
    pair<LL, int> query(int i, int l, int r)
    {
        if (l <= t[i].l && t[i].r <= r)
        {
            pair<LL, int> tt = make_pair(t[i].pstate, t[i].mul);
            return tt;
        }
        push_down(i);
        int mid = (t[i].l + t[i].r) >> 1;
        if (l > mid) return query(i << 1 | 1, l, r);
        else if (r <= mid) return query(i << 1, l, r);
        else 
        {
            pair<LL, int> ls = query(i << 1, l, r);
            pair<LL, int> rs = query(i << 1 | 1, l, r);
            ls.first |= rs.first;
            ls.second = 1LL * ls.second * rs.second % mod;
            return ls;
        }
    }
    
    int main()
    {
        #ifdef ZYCMH
        freopen("1.in", "r", stdin);
        freopen("1.out", "w", stdout);
        #endif
        get_prime(300);
        scanf("%d%d", &n, &m);
        for (int i = 1; i <= n; i ++ )
            scanf("%d", &a[i]);
    
        build(1, 1, n);
        
        for (int i = 1; i <= m; i ++ )
        {
            char s[10];
            scanf("%s", s);
            if (s[0] == 'T') 
            {
                int l, r;
                scanf("%d%d", &l, &r);
                pair<LL, int> t = query(1, l, r);
                int ans = t.second;
                LL pstate = t.first;
                for (int j = 1; j <= p[0]; j ++ )
                    if (pstate & (1LL << (j - 1)))
                        ans = 1LL * ans * (p[j] - 1) % mod * qpow(p[j], mod - 2) % mod;
                printf("%d\n", ans);
            }
            else 
            {
                int l, r, x;
                scanf("%d%d%d", &l, &r, &x);
                LL xp = 0;
                for (int j = 1; j <= p[0]; j ++ )
                    if (x % p[j] == 0) 
                        xp += (1LL << (j - 1));
                update(1, l, r, x, xp);
            }
        }
        return 0;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
  • 相关阅读:
    yolo增加MPDIoU loss
    运行obotframework-ride控制台报错module ‘urllib‘ has no attribute ‘Request‘
    洛谷_P1320、P1830 压缩技术和轰炸Ⅲ
    如何选择一款好用的物业管理软件?快鲸物业管理软件是不二之选
    暑假加餐|有钱人和你想的不一样(第15天)+财富与金钱的秘密【干货】
    Linux内存状态监测工具smem命令 | 如何在#linux OS下找到特定进程的交换(swap)空间使用情况?
    pytest(8)-参数化
    Windows 10 远程桌面连接
    SpringBoot项目创建-基础篇
    [云原生k8s] k8s资源限制以及探针检查
  • 原文地址:https://blog.csdn.net/cpp_juruo/article/details/126669632